Compare commits

..

992 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 56ff85a36b Moodle release 3.3.6 2018-05-16 18:42:13 +02:00
Marina Glancy c2a6b2b6ec MDL-62469 qtype_calculated: check remaining placeholders, see MDL-62275 2018-05-16 17:40:52 +02:00
David Monllao 96b0818716 Merge branch 'MDL-62456_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-16 08:58:53 +02:00
Andrew Nicols 51f0dbbcda Merge branch 'wip-MDL-62147-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-16 14:30:03 +08:00
Jun Pataleta 1465548ba5 Merge branch 'MDL-62463-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-16 14:21:22 +08:00
Frédéric Massart 06c8d3bf55 MDL-62147 core_grades: Report contexts and data related to scales 2018-05-16 13:53:04 +08:00
Marina Glancy fd982f3030 MDL-62147 core_grades: Declare metadata of scales and import tables 2018-05-16 13:53:04 +08:00
Marina Glancy 876cdf05c4 MDL-62147 portfolio: add missing tables to privacy provider 2018-05-16 13:53:01 +08:00
Marina Glancy b98339b09a MDL-62147 privacy: unittest ensures that all tables covered 2018-05-16 13:52:58 +08:00
Andrew Nicols 4b6f3f6cc1 MDL-62463 mod_glossary: Fix SQL query
The query was doing:
WHERE c.id ... AND ... OR ... OR ...

Which equates to:
WHERE (c.id ... AND ...) OR ... OR ...

Adding parens to:
WHERE (c.id ... AND (... OR ... OR ...))
2018-05-16 13:50:40 +08:00
Marina Glancy 8862838f25 MDL-62147 privacy: corrections to tables, temporary tables 2018-05-16 12:48:29 +08:00
Mark Nelson 5255e8fea9 MDL-62456 mod_lti: add missing add_external_location_link call 2018-05-16 12:23:49 +08:00
Jake Dallimore decd3731df Merge branch 'MDL-62134-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-16 12:02:54 +08:00
Andrew Nicols 60f6712ce1 MDL-62134 core_privacy: Allow for a failure handler 2018-05-16 11:52:46 +08:00
Andrew Nicols 8d85f96696 Merge branch 'MDL-62426-33' of https://github.com/snake/moodle into MOODLE_33_STABLE 2018-05-16 11:02:51 +08:00
Jake Dallimore 23a203618c MDL-62426 core_enrol: control enrolment subcontexts at the provider
Added a function to the core_enrol provider allowing enrol plugins
to set their subcontext relative to a fixed 'enrolments' parent dir.
2018-05-16 10:24:34 +08:00
Jake Dallimore c0c33ab059 MDL-62426 enrol_flatfile: make provider a plugin provider
The enrol_flatfile table can contain userdata relating to pending
enrolments, so this should be exported and deleted as necessary.
2018-05-16 09:36:37 +08:00
Marina Glancy 691e92efa7 MDL-62134 privacy: consistantly call components methods 2018-05-16 09:05:42 +08:00
Eloy Lafuente (stronk7) 1b70269f4e Merge branch 'MDL-62448-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-15 17:29:24 +02:00
Sara Arjona 8197937d22 MDL-62448 block_rss_client: Export all feeds from Privacy API 2018-05-15 14:27:16 +02:00
David Monllao d60618cbea Merge branch 'MDL-62228_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-15 13:31:56 +02:00
David Monllao ac897aedea weekly release 3.3.5+ 2018-05-15 09:42:09 +02:00
David Monllao 6582329fdf Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-05-15 09:42:07 +02:00
Mark Nelson e8279ab994 MDL-62228 core: remove unnecessary context check in privacy providers 2018-05-15 12:02:52 +08:00
Andrew Nicols 85d42a024b Merge branch 'MDL-62444-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-05-15 11:39:25 +08:00
Andrew Nicols 1ea41504b4 Merge branch 'MDL-62428_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-15 11:06:01 +08:00
Zig Tan 8195484581 MDL-62444 mod_assignment: Fix missing lang string. 2018-05-15 10:02:54 +08:00
Jun Pataleta 04f3435b12 Merge branch 'MDL-62432-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-15 09:34:04 +08:00
Andrew Nicols 00ced8dde3 MDL-62432 quiz: Check contexts more carefully 2018-05-15 09:25:51 +08:00
Eloy Lafuente (stronk7) d33d90031e Merge branch 'MDL-62430_33' of git://github.com/dmonllao/moodle into MOODLE_33_STABLE 2018-05-15 02:56:23 +02:00
AMOS bot b26b312e46 Automatically generated installer lang files 2018-05-15 00:06:41 +00:00
David Monllao f90a0107d1 MDL-62430 block_html: Check that block instances are block_html 2018-05-14 17:07:21 +02:00
David Monllao f6d8b2f753 Merge branch 'MDL-62370-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-14 16:01:21 +02:00
Andrew Nicols 533ef686e4 Merge branch 'MDL-62356-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-05-14 21:03:03 +08:00
Andrew Nicols 3fe971f407 Merge branch 'MDL-62357-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-05-14 20:47:33 +08:00
Andrew Nicols d334974409 MDL-62370 core_privacy: Directory-less subsystems are compliant 2018-05-14 20:04:41 +08:00
Marina Glancy e58797fb4c MDL-62430 privacy: validate context when deleting all user data 2018-05-14 18:13:52 +08:00
cescobedo ed333da1a8 MDL-62356 enrol_meta: Add privacy implementation for enrol_meta 2018-05-14 10:59:22 +02:00
David Monllao ef9428e9cb Merge branch 'MDL-62425-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-14 10:59:13 +02:00
cescobedo 112aa66679 MDL-62357 enrol_cohort: Add privacy implementation for enrol_cohort 2018-05-14 10:48:16 +02:00
Andrew Nicols 974a90e2e7 MDL-62425 core: Add privacy implementation 2018-05-14 15:44:59 +08:00
Andrew Nicols 674544a52a MDL-62425 core_privacy: Add core to the list of components 2018-05-14 15:43:26 +08:00
Mark Nelson b30fadbae0 MDL-62428 core: fix incorrect early return in privacy providers 2018-05-14 13:08:02 +08:00
Jake Dallimore ccc3f70717 Merge branch 'MDL-62420-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-14 11:58:28 +08:00
Jake Dallimore 2c5e158be1 Merge branch 'MDL-62393-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-14 09:38:18 +08:00
Andrew Nicols f9180359e6 MDL-62420 enrol_lti: Fix random unit test fail in privacy 2018-05-14 08:44:25 +08:00
Eloy Lafuente (stronk7) d567be0d04 Merge branch 'MDL-62371-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-14 02:42:27 +02:00
Eloy Lafuente (stronk7) 98900443b7 Merge branch 'MDL-62251-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-05-13 23:58:26 +02:00
Andrew Nicols 6d86e2d223 MDL-62371 core_privacy: Add support for progress trace 2018-05-13 15:45:24 +08:00
AMOS bot ab6abffb30 Automatically generated installer lang files 2018-05-13 00:06:57 +00:00
Andrew Nicols 018135947a MDL-62393 message: Fix random unit test fails 2018-05-12 23:02:49 +08:00
Eloy Lafuente (stronk7) 374387c563 weekly release 3.3.5+ 2018-05-12 12:56:41 +02:00
Eloy Lafuente (stronk7) 6ed62aec00 MDL-62275 qtype_calculatedmulti: Fix typo 2018-05-11 21:17:46 +02:00
David Monllao 776503b29a MDL-62029 core_course: Site format is not a standard plugin 2018-05-11 20:19:19 +02:00
Eloy Lafuente (stronk7) 92928baabe Merge branch 'MDL-62384-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-11 18:28:11 +02:00
David Monllao 1560349956 Merge branch 'MDL-61858_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-11 18:07:16 +02:00
David Monllao f39b2d7da8 Merge branch 'MDL-62368_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-11 17:59:36 +02:00
Mark Nelson 739e7f5c79 MDL-61858 gradingform_guide: added missing metadata implementation 2018-05-11 19:42:08 +08:00
Mark Nelson 3747401992 MDL-61858 core_portfolio: added missing metadata implementation 2018-05-11 19:42:08 +08:00
Andrew Nicols e34f261d5e MDL-61858 core_privacy: Add test to ensure component implementations 2018-05-11 19:42:08 +08:00
Eloy Lafuente (stronk7) 7bf7b7e517 Merge branch 'MDL-61951-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-11 13:24:02 +02:00
Sara Arjona 791113dd66 MDL-61951 core_grading: Review SQL to avoid Oracle errors 2018-05-11 13:02:58 +02:00
David Monllao 56141c546f Merge branch 'MDL-61714-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-11 11:31:42 +02:00
Sara Arjona c52dac659c MDL-61714 admin: Removed Slovenian digital age 2018-05-11 10:14:20 +02:00
Shamim Rezaie 41960dcbe8 MDL-62251 Privacy: Fix dir separator in export_file() 2018-05-11 17:44:45 +10:00
Shamim Rezaie 0a65299f7f MDL-62251 Privacy: Url path separator should be platform independant
It should always be forward slash.
2018-05-11 17:43:10 +10:00
Shamim Rezaie f6f1a5f624 MDL-62251 Privacy: Fix get_path() and get_full_path() bug in Windows 2018-05-11 17:39:54 +10:00
Shamim Rezaie 96437cfa3e MDL-62251 backup: Fix replace_tempdir() bug under Windows
rename() fails under Windows if the destination file/directory exists.
I modified the code to only call $this->get_workdir_path() once as that function
creates the directory if doesn't exist. And we don't want that considering the
behaviour of rename on Windows.
2018-05-11 17:37:03 +10:00
Mark Nelson 94f668496c MDL-62368 enrol_lti: implement privacy provider 2018-05-11 15:15:41 +08:00
Eloy Lafuente (stronk7) c31ed14f78 MDL-62354 notes: Reduce string to avoid js_call_amd() lenght limits
That way we are under the max 1024 allowed and also, the help string
is shown properly in the modal (previously part of it was not visible
falling off-window).
2018-05-11 14:53:22 +08:00
Jun Pataleta f6636c4ef6 Merge branch 'MDL-62394-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-11 14:23:25 +08:00
Andrew Nicols 348bdcba70 MDL-62394 privacy: Make JSON export pretty 2018-05-11 14:12:55 +08:00
Mihail Geshoski 7db992398f MDL-62384 privacy: Modify user contexts query for auth_oauth2 2018-05-11 11:14:35 +08:00
Andrew Nicols 6be954134b MDL-62384 core_rating: Move WHERE clauses to JOIN 2018-05-11 11:14:35 +08:00
Andrew Nicols dafd1528c1 MDL-62384 core_grade: Move WHERE clause to JOIN 2018-05-11 11:14:34 +08:00
Andrew Nicols 6951d69b81 MDL-62384 mod_lesson: Move WHERE clause to JOIN 2018-05-11 11:14:34 +08:00
Andrew Nicols 0e9baa7675 MDL-62384 logstore_standard: Remove unnecessary join on context 2018-05-11 11:14:33 +08:00
Andrew Nicols a3aaf32b0a MDL-62384 mod_quiz: Improve performancy of privacy queries 2018-05-11 11:14:32 +08:00
Adrian Greeve a2137340ae MDL-62384 mod_data: Update sql to improve performance. 2018-05-11 11:14:32 +08:00
Adrian Greeve fb7934b2b8 MDL-62384 tool_monitor: Update to sql to fix performance. 2018-05-11 11:14:31 +08:00
Adrian Greeve 2c030c2ccc MDL-62384 core_competency: Update to sql to increase performance. 2018-05-11 11:14:30 +08:00
Adrian Greeve 8de1eaa03b MDL-62384 core_completion: Update to sql to improve performance. 2018-05-11 11:14:30 +08:00
Adrian Greeve b2481afc98 MDL-62384 mod_assign: Update to sql query for performance. 2018-05-11 11:14:30 +08:00
Andrew Nicols c0e4458f28 Merge branch 'wip-MDL-61814-33-fix' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-05-11 10:50:23 +08:00
Adrian Greeve f3bd9db07c MDL-61814 report_stats: Update to sql to increase performance. 2018-05-11 10:42:22 +08:00
Jake Dallimore 83038cdb43 MDL-61951 core_grading: SQL improvements for grading_instance join 2018-05-11 10:20:20 +08:00
Jake Dallimore d1ec251117 Merge branch 'MDL-61951-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-11 10:20:14 +08:00
Jun Pataleta a54eadb25a Merge branch 'MDL-62117-33-fix' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-11 09:30:19 +08:00
Andrew Nicols 5bd702aace MDL-62117 enrol_paypal: Improve SQL efficiency 2018-05-11 08:53:20 +08:00
Tim Hunt 9d1bc62c35 MDL-62275 qtype_calc*: improve validation of formulae
Many thanks to Marina Glancy for helping with this.
2018-05-11 01:33:54 +02:00
David Monllao de464f7105 MDL-62200 css: Updating compiled build 2018-05-10 19:28:24 +02:00
David Monllao ab4ecb487d Merge branch 'MDL-62366-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-05-10 18:14:00 +02:00
David Monllao 3bd2c9cc2d Merge branch 'MDL-61714-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-10 18:11:52 +02:00
David Monllao 255bc952ba Merge branch 'MDL-62200-33' of git://github.com/bmbrands/moodle into MOODLE_33_STABLE 2018-05-10 18:04:31 +02:00
David Monllao 7eb75ea17c Merge branch 'MDL-61949-33-privacy-upgrade-txt' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-05-10 17:53:21 +02:00
Jake Dallimore 9429e8c3ea MDL-61951 core_grading: Several fixes to the privacy implementation
- Fixed legacy polyfill method definitions
- Added unit test for legacy polyfill
- Fixed delete_gradingform_for_userid in gradingform provider
2018-05-10 13:27:03 +02:00
Andrew Nicols 0c392c1a85 MDL-61905 mod_workshop: Adjust privacy SQL queries
This change moves the content of WHERE to the JOIN, thus filtering the
results before they are returned. This reduces the number of joined rows
which gives a big performance benefit.
2018-05-10 13:06:08 +02:00
David Mudrák 9708ed8762 MDL-61949 privacy: Add mention of the new API in upgrade.txt files
The notice is explicitly repeated for activity modules because they
usually process user data heavily.
2018-05-10 12:07:28 +02:00
Eloy Lafuente (stronk7) 7a797d3fe5 Merge branch 'MDL-62354-33-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-05-10 11:39:32 +02:00
Sara Arjona 7658ef16d5 MDL-61714 admin: Update digital age consent map according legislation 2018-05-10 10:33:51 +02:00
Helen Foster c37224a097 MDL-62354 lang: Merge English strings from the en_fix language pack
Significant string changes:

* publishstate_help, core_notes - including GDPR guidance
2018-05-10 09:34:48 +02:00
David Monllao 5439bb15fe Merge branch 'MDL-61309-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-10 08:49:35 +02:00
Andrew Nicols ae396e60f1 MDL-61309 mod_forum: Improve privacy query performance 2018-05-10 14:06:43 +08:00
Sara Arjona 8e72596812 MDL-61951 grading: Implement privacy API 2018-05-10 07:54:11 +02:00
Marina Glancy 0fa43bbd16 MDL-62206 blocks: do not add fixed form elements as hidden 2018-05-10 12:09:05 +08:00
Adam Olley e3a7ffba7d MDL-62210 mod_assign: limit file lookup to the target assign 2018-05-10 11:22:08 +08:00
Brendan Cox 0f3b121f1a MDL-62210 mod_assign: improved validation in portfolio caller class 2018-05-10 11:22:08 +08:00
Jake Dallimore a5a7741d7c Merge branch 'MDL-62383-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-05-10 10:04:43 +08:00
Jun Pataleta b141b2d185 MDL-62383 privacy: Close recordset in contextlist::add_from_sql() 2018-05-10 09:57:02 +08:00
Jake Dallimore 2e0e356228 MDL-62257 mnetservice_enrol: minor fixes to privacy provider 2018-05-10 09:38:20 +08:00
Jake Dallimore a3a8c5b244 Merge branch 'MDL-62257-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-05-10 09:38:15 +08:00
Eloy Lafuente (stronk7) c092051695 Merge branch 'MDL-61309-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-10 09:19:47 +08:00
David Monllao 8f9e7916e7 Merge branch 'MDL-62308_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-10 09:19:47 +08:00
David Monllao 973405d146 MDL-61976 mod_wiki: Trim returned value to avoid EOF-related failures 2018-05-10 09:19:47 +08:00
Andrew Nicols e676202902 Merge branch 'wip-MDL-62351-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-10 09:19:46 +08:00
David Monllao 7f8fbfe6c7 Merge branch 'MDL-62249-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-05-10 09:19:46 +08:00
Andrew Nicols c606e82d4b Merge branch 'MDL-62217_33' of git://github.com/dmonllao/moodle into MOODLE_33_STABLE 2018-05-10 09:19:45 +08:00
Andrew Nicols f0bec9ecdf Merge branch 'MDL-62269-33' of git://github.com/vmdef/moodle into MOODLE_33_STABLE 2018-05-10 09:19:45 +08:00
David Monllao fd2bb53bf2 Merge branch 'wip-MDL-61976-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-10 09:19:44 +08:00
David Monllao 2465c76ac1 MDL-61994 mod_glossary: Fixing wrong subsystem name 2018-05-10 09:19:44 +08:00
David Monllao e04bb65283 Merge branch 'MDL-61994-33' of git://github.com/lameze/moodle into MOODLE_33_STABLE 2018-05-10 09:19:44 +08:00
David Monllao af90c1bc4b Merge branch 'MDL-61309-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-10 09:19:43 +08:00
Jun Pataleta 4458f71ab0 MDL-62232 mod_forum: PHPUnit 5.5 needs expectException() 2018-05-10 09:19:43 +08:00
Brendan Cox aa208d1bc2 MDL-62232 mod_forum: Additional tests for portfolio file export 2018-05-10 09:19:42 +08:00
Adam Olley 30ca2558dc MDL-62232 mod_forum: Limit portfolio to files belonging to the post 2018-05-10 09:19:42 +08:00
Andrew Nicols c1fef4c9c3 Merge branch 'MDL-61905-33-privacyworkshop' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-05-10 09:19:41 +08:00
Andrew Nicols 524cd5de9c Merge branch 'MDL-62029-33-2' of git://github.com/snake/moodle into MOODLE_33_STABLE 2018-05-10 09:19:41 +08:00
Jun Pataleta 908ba9fe26 Merge branch 'MDL-62332-33' of git://github.com/bmbrands/moodle into MOODLE_33_STABLE 2018-05-10 09:19:40 +08:00
Andrew Nicols dce8813021 Merge branch 'MDL-62318-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-05-10 09:19:40 +08:00
Andrew Nicols 9c2f2a1ac0 Merge branch 'MDL-62117-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-05-10 09:19:40 +08:00
Marina Glancy f83de6d1ba MDL-62233 portfolio: check caller parent class 2018-05-10 09:19:39 +08:00
Zig Tan c47cccc329 MDL-62366 mod_assign: Followup fix for attemptnumber in exported JSON 2018-05-10 09:19:35 +08:00
Andrew Nicols 219ede6ecf MDL-61309 mod_forum: Remove unnecessary deletion check 2018-05-10 07:48:26 +08:00
Mark Nelson 9b7c011e3d MDL-62308 core_backup: implement privacy provider
The provider was added to 'backup/util/ui/' due to
Moodle's implementation of autoclass loading. See
fetch_subsystems() in lib/classes/component.php.
2018-05-09 23:17:27 +08:00
Marina Glancy f88e03e50a MDL-62351 privacy: check that subsystem/plugintype exist 2018-05-09 17:37:58 +08:00
Marina Glancy 369181e33b MDL-61976 mod_wiki: implement privacy API 2018-05-09 17:31:05 +08:00
Victor Deniz 89266764c0 MDL-62269 auth_mnet: Implement privacy API
AMOS BEGIN
 CPY [privacy:metadata:address,core_user],[privacy:metadata:mnet_external:address,auth_mnet]
 CPY [privacy:metadata:aim,core_user],[privacy:metadata:mnet_external:aim,auth_mnet]
 CPY [privacy:metadata:aim,core_user],[privacy:metadata:mnet_external:aim,auth_mnet]
 CPY [privacy:metadata:alternatename,core_user],[privacy:metadata:mnet_external:alternatename,auth_mnet]
 CPY [privacy:metadata:autosubscribe,core_user],[privacy:metadata:mnet_external:autosubscribe,auth_mnet]
 CPY [privacy:metadata:calendartype,core_user],[privacy:metadata:mnet_external:calendartype,auth_mnet]
 CPY [privacy:metadata:city,core_user],[privacy:metadata:mnet_external:city,auth_mnet]
 CPY [privacy:metadata:country,core_user],[privacy:metadata:mnet_external:country,auth_mnet]
 CPY [privacy:metadata:currentlogin,core_user],[privacy:metadata:mnet_external:currentlogin,auth_mnet]
 CPY [privacy:metadata:department,core_user],[privacy:metadata:mnet_external:department,auth_mnet]
 CPY [privacy:metadata:description,core_user],[privacy:metadata:mnet_external:description,auth_mnet]
 CPY [privacy:metadata:email,core_user],[privacy:metadata:mnet_external:email,auth_mnet]
 CPY [privacy:metadata:emailstop,core_user],[privacy:metadata:mnet_external:emailstop,auth_mnet]
 CPY [privacy:metadata:firstaccess,core_user],[privacy:metadata:mnet_external:firstaccess,auth_mnet]
 CPY [privacy:metadata:firstname,core_user],[privacy:metadata:mnet_external:firstname,auth_mnet]
 CPY [privacy:metadata:firstnamephonetic,core_user],[privacy:metadata:mnet_external:firstnamephonetic,auth_mnet]
 CPY [privacy:metadata:icq,core_user],[privacy:metadata:mnet_external:icq,auth_mnet]
 CPY [privacy:metadata:id,core_user],[privacy:metadata:mnet_external:id,auth_mnet]
 CPY [privacy:metadata:idnumber,core_user],[privacy:metadata:mnet_external:idnumber,auth_mnet]
 CPY [privacy:metadata:imagealt,core_user],[privacy:metadata:mnet_external:imagealt,auth_mnet]
 CPY [privacy:metadata:institution,core_user],[privacy:metadata:mnet_external:institution,auth_mnet]
 CPY [privacy:metadata:lang,core_user],[privacy:metadata:mnet_external:lang,auth_mnet]
 CPY [privacy:metadata:lastaccess,core_user],[privacy:metadata:mnet_external:lastaccess,auth_mnet]
 CPY [privacy:metadata:lastlogin,core_user],[privacy:metadata:mnet_external:lastlogin,auth_mnet]
 CPY [privacy:metadata:lastname,core_user],[privacy:metadata:mnet_external:lastname,auth_mnet]
 CPY [privacy:metadata:lastnamephonetic,core_user],[privacy:metadata:mnet_external:lastnamephonetic,auth_mnet]
 CPY [privacy:metadata:maildigest,core_user],[privacy:metadata:mnet_external:maildigest,auth_mnet]
 CPY [privacy:metadata:maildisplay,core_user],[privacy:metadata:mnet_external:maildisplay,auth_mnet]
 CPY [privacy:metadata:middlename,core_user],[privacy:metadata:mnet_external:middlename,auth_mnet]
 CPY [privacy:metadata:msn,core_user],[privacy:metadata:mnet_external:msn,auth_mnet]
 CPY [privacy:metadata:phone,core_user],[privacy:metadata:mnet_external:phone1,auth_mnet]
 CPY [privacy:metadata:picture,core_user],[privacy:metadata:mnet_external:picture,auth_mnet]
 CPY [privacy:metadata:policyagreed,core_user],[privacy:metadata:mnet_external:policyagreed,auth_mnet]
 CPY [privacy:metadata:skype,core_user],[privacy:metadata:mnet_external:skype,auth_mnet]
 CPY [privacy:metadata:suspended,core_user],[privacy:metadata:mnet_external:suspended,auth_mnet]
 CPY [privacy:metadata:timezone,core_user],[privacy:metadata:mnet_external:timezone,auth_mnet]
 CPY [privacy:metadata:trackforums,core_user],[privacy:metadata:mnet_external:trackforums,auth_mnet]
 CPY [privacy:metadata:trustbitmask,core_user],[privacy:metadata:mnet_external:trustbitmask,auth_mnet]
 CPY [privacy:metadata:url,core_user],[privacy:metadata:mnet_external:url,auth_mnet]
 CPY [privacy:metadata:username,core_user],[privacy:metadata:mnet_external:username,auth_mnet]
 CPY [privacy:metadata:yahoo,core_user],[privacy:metadata:mnet_external:yahoo,auth_mnet]
AMOS END
2018-05-09 10:00:13 +01:00
David Monllao 2a869c727e MDL-62217 search_solr: Plugin provider fake implementation 2018-05-09 10:59:14 +02:00
David Monllao 7a5aee27ff MDL-62217 search: Privacy providers 2018-05-09 10:58:26 +02:00
David Mudrák 9515077330 MDL-61905 workshop: Implement privacy API in grading evaluators
Standard workshop ships with only one evaluation method and that one
holds no personal data.
2018-05-09 10:03:31 +02:00
David Mudrák 0f84929153 MDL-61905 workshop: Implement privacy API in assessment allocators
Assessment allocation methods normally do not store any personal data.
Their duty is to create assessment records that are then exported by the
workshop core itself.

Still, some allocators (such as the Manual allocation) can store certain
personal data such as user preferences.
2018-05-09 10:03:31 +02:00
David Mudrák be19685f6b MDL-61905 workshop: Implement privacy API in grading strategies
On low level, standard grading strategies subplugins do not store
personal themselves.  They make use of the grades storage provided by
the workshop itself.  What they do contain though is the information
about how the assessment forms were defined. And they are also
responsible for correctly interpreting the values in the central grades
table.

Grading strategies fulfil the contract with the parent workshop module
by implementing the workshopform_provider interface. That gives them a
chance to export data about the assessment form to each of exported
assessment.
2018-05-09 10:03:31 +02:00
David Mudrák d3ae85a539 MDL-61905 workshop: Implement the privacy API in the workshop core
Workshop module stores personal data in its tables, via user
preference and via core_files and core_plagiarism subsystems.

When exporting the data, we export not only data created by users
themselves (such as their submissions and provided peer-assessments) but
also all relevant data that can (or must) be used to interpret created
content and evaluate the user's performance and skills.

On the other hand, when deleting data at user's request, we delete only
those data that do not affect other users' performance evaluation. The
reasoning is that one's right for privacy does not overweight someone
else's right for fair assessment. For that reason, we can't fully delete
whole provided peer-assessments, for example. Because they are used in
cross-comparison and grading evaluation of all other peers who assessed
the same submission. So instead, we replace provided texts but still
keep the original record.

Workshop defines the interface for its grading strategy subplugins to
allow them attach personal data under their control to the exported
structures.
2018-05-09 10:03:31 +02:00
Jake Dallimore 9e25c063b7 MDL-62029 core_course: Fixes to context-aware provider implementation. 2018-05-09 15:48:15 +08:00
Andrew Nicols 21e93fdbe3 MDL-61309 mod_forum: Implement privacy deletion 2018-05-09 14:03:34 +08:00
Andrew Nicols 2fefe3ca68 MDL-61309 mod_forum: Implement the Privacy API 2018-05-09 14:03:33 +08:00
Andrew Nicols 6b6226160d MDL-61309 core_tags: Add privacy unit test trait 2018-05-09 13:52:59 +08:00
Simey Lameze 97c77877f7 MDL-61994 mod_glossary: add unit tests for provider 2018-05-09 12:15:58 +08:00
Simey Lameze 04fe8c2a63 MDL-61994 mod_glossary: implement privacy providers 2018-05-09 12:15:53 +08:00
Shamim Rezaie 80936f77ef MDL-62318 core_group: Updating cache when deleting group memberships 2018-05-09 13:35:18 +10:00
Shamim Rezaie 9c172adefe MDL-62318 core_group: Add implementation of privacy API 2018-05-09 13:35:11 +10:00
Adrian Greeve d7882b3815 MDL-62029 core_privacy: context aware provider creation. 2018-05-09 09:39:59 +08:00
Adrian Greeve e2ba4fd896 MDL-62029 core_course: Create privacy files for core_course. 2018-05-09 09:39:51 +08:00
Marina Glancy 7981a0b125 MDL-61996 core: when loggedin always check user is complete 2018-05-09 02:56:56 +02:00
Andrew Nicols 856b970904 Merge branch 'MDL-62010-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-05-09 08:53:56 +08:00
cescobedo af9f57975c MDL-62010 core_enrol: Add privacy implementation for core_enrol 2018-05-08 19:04:37 +02:00
David Monllao 8322e9a1ee MDL-61814 core_user: Remove empty line to avoid ci warning 2018-05-08 17:20:18 +02:00
David Monllao 6817208044 Merge branch 'wip-MDL-61814-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-05-08 17:20:04 +02:00
David Monllao 5eae39feb0 Merge branch 'MDL-61943-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-05-08 16:44:17 +02:00
David Monllao e77114bf70 weekly release 3.3.5+ 2018-05-08 14:02:11 +02:00
David Monllao 3da5a3c348 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-05-08 14:02:09 +02:00
cescobedo a6c263e33d MDL-61943 core_role: Add privacy implementation for core_role 2018-05-08 13:50:37 +02:00
Bas Brands 10662a78b9 MDL-62332 Theme boost: paging bar empty active link 2018-05-08 10:10:47 +02:00
cescobedo dfd93e3617 MDL-62257 mnetservice_enrol: Implement Privacy API 2018-05-08 10:06:32 +02:00
Andrew Nicols 6554a3d31e Merge branch 'wip-MDL-61937-33-fix' of https://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-08 14:45:40 +08:00
Marina Glancy 767e94894a MDL-61937 mod_data: fix commentarea name 2018-05-08 14:40:38 +08:00
Adrian Greeve c875879050 MDL-61814 report_stats: Update to be a full privacy provider. 2018-05-08 14:35:47 +08:00
Adrian Greeve 18920002b9 MDL-61814 core_portfolio: Update to portfolio provider. 2018-05-08 14:35:47 +08:00
Adrian Greeve 08c3fc7493 MDL-61814 core_user: Implement privacy system for user. 2018-05-08 14:35:47 +08:00
Zig Tan eda9ba5e21 MDL-62249 block_tag_flickr: Corrected privacy providers 2018-05-08 12:17:44 +08:00
Marina Glancy 7ceb3f8568 MDL-61976 privacy: replace pluginfile in test writer 2018-05-08 12:03:18 +08:00
Marina Glancy 5a4cbdb34f MDL-61976 privacy: add subcontext argument to has_any_data 2018-05-08 12:03:18 +08:00
Andrew Nicols 3ff77e753b Merge branch 'wip-MDL-62068-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-08 11:48:35 +08:00
Marina Glancy 669fba527d MDL-62068 core_tag: implement privacy API 2018-05-08 11:35:14 +08:00
Shamim Rezaie 31842699a0 MDL-62117 enrol_paypal: Add implementation of Privacy API 2018-05-08 13:30:09 +10:00
Andrew Nicols eb8a915468 Merge branch 'MDL-62285-33' of git://github.com/ryanwyllie/moodle into MOODLE_33_STABLE 2018-05-08 11:16:20 +08:00
Ryan Wyllie c8c5d741ab MDL-62285 privacy: use context id when generating context path
moodle_content_writer::get_context_path() now includes the context
id in the path to ensure that it will always generate unique paths
even when the context names are not unique.
2018-05-08 01:41:45 +00:00
Eloy Lafuente (stronk7) 94f42309c5 Merge branch 'MDL-61521-33' of git://github.com/jleyva/moodle into MOODLE_33_STABLE 2018-05-08 01:45:44 +02:00
David Monllao 5fd78d27ae Merge branch 'MDL-62326-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-07 12:11:22 +02:00
Andrew Nicols 77518888c8 MDL-62326 core_antivirus: Implement null provider 2018-05-07 17:37:18 +08:00
Andrew Nicols 9b3ce309f7 Merge branch 'MDL-62169-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-05-07 17:27:18 +08:00
Zig Tan c13aaef075 MDL-62169 mod_assignment: Improved phpunit test reliability 2018-05-07 16:46:07 +08:00
Andrew Nicols 19afe6488f Merge branch 'MDL-61919_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-07 15:53:33 +08:00
Andrew Nicols f819f0f992 Merge branch 'wip-MDL-62137-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-05-07 15:30:49 +08:00
Adrian Greeve 3c38e56b83 MDL-62137 core_privacy: Update to helper to use core_completion 2018-05-07 14:22:50 +08:00
Adrian Greeve a3b8f6a288 MDL-62137 core_completion: Privacy files for core_completion. 2018-05-07 14:22:50 +08:00
Andrew Nicols 266d7f04ff Merge branch 'MDL-62169-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-05-07 14:18:56 +08:00
Zig Tan 3f6f7b1804 MDL-62169 mod_assignment: Implemented privacy providers 2018-05-07 13:52:43 +08:00
Andrew Nicols 01bde600e3 Merge branch 'MDL-61407-33-fix' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-05-07 13:52:22 +08:00
Jun Pataleta 3a2e28454d MDL-61407 mod_quiz: Determine quiz step for manual comment 2018-05-07 13:42:17 +08:00
Andrew Nicols e178d5ec21 MDL-61937 mod_data: Correct rating export args in privacy 2018-05-07 09:43:28 +08:00
David Monllao a5543d0731 MDL-61937 mod_data: Target the correct area 2018-05-07 09:43:27 +08:00
Andrew Nicols 820148bd89 MDL-61407 question: Export step files in privacy 2018-05-07 07:10:19 +08:00
Eloy Lafuente (stronk7) 39558fa5dd MDL-61693 core_calendar: make results deterministic for better testing 2018-05-06 18:17:52 +02:00
Eloy Lafuente (stronk7) 99c76ad3ce Merge branch 'MDL-62315-33-privacycoreform' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-05-04 15:42:11 +02:00
Bas Brands 3372b77957 MDL-62200 Theme boost: popup in popup styles 2018-05-04 14:10:08 +02:00
David Mudrák eddf0a076f MDL-62315 form: Fix privacy API implementation for core_form subsystem
Only during the testing, we realized that the user preference was added
only in 3.4 in MDL-59407 so we have to declare no personal data in 3.3.
No need for custom unit test as the implementation is covered by
privacy/tests/provider_test.php
2018-05-04 13:08:57 +02:00
Frédéric Massart 101f6c43e1 MDL-61877 core_competency: False negative due to random ordering 2018-05-04 11:18:52 +02:00
Zig Tan 3da2da51b8 MDL-61693 core_calendar: Simplified get calendar event details SQL 2018-05-04 13:10:28 +08:00
Jake Dallimore df122c79cd Merge branch 'MDL-61407-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-04 11:59:31 +08:00
Andrew Nicols e6c53933a5 Merge branch 'wip-MDL-61937-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-04 11:30:29 +08:00
Jun Pataleta 34dcee8f34 Merge branch 'MDL-61877-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-05-04 11:24:08 +08:00
Marina Glancy e3c8b00866 MDL-61937 mod_data: implement privacy provider 2018-05-04 11:21:47 +08:00
Marina Glancy 5c3ee69c74 MDL-61937 tag: new method in privacy api 2018-05-04 11:21:41 +08:00
Marina Glancy bcd7e54804 MDL-61937 rating: delete method in privacy provider 2018-05-04 11:21:04 +08:00
Marina Glancy 8d141bb1ef MDL-61937 comment: do not use API in provider
When exporting comments we can not use comments API because:
- we don't need to call component validate, comments may be disabled right now but
  are still stored
- we don't need to call display callback
- we need to export all comments and not only first 15 of them
2018-05-04 11:21:04 +08:00
Marina Glancy d1778bc5a0 MDL-61937 mod_data: generator for all field types 2018-05-04 11:21:01 +08:00
cescobedo 156233b745 MDL-61937 datafield: Add privacy implementation for all datafield 2018-05-04 11:20:46 +08:00
Mark Nelson 88f53cf84e MDL-61919 core_message: implement privacy provider 2018-05-04 11:17:47 +08:00
Jake Dallimore 111f55d95e Merge branch 'MDL-62046-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-05-04 10:28:08 +08:00
Jake Dallimore ddc0b2c805 Merge branch 'MDL-62032-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-05-04 09:57:36 +08:00
Jake Dallimore 9acdfbcdda Merge branch 'MDL-62030-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-05-04 09:52:16 +08:00
Jake Dallimore 421628ec0b Merge branch 'MDL-59845-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-04 09:48:12 +08:00
Jake Dallimore 61cf3e9178 Merge branch 'MDL-62007-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-05-04 09:23:29 +08:00
Eloy Lafuente (stronk7) cefc325958 Merge branch 'MDL-62315-33-privacycoreform' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-05-03 23:40:57 +02:00
Eloy Lafuente (stronk7) 2886a5e64d Merge branch 'MDL-61800-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-03 23:29:28 +02:00
David Mudrák 8da3291abb MDL-62315 form: Implement the privacy API for core_form subsystem
Forms subsystem has no own database table. The only personal data is the
user preference 'filemanager_recentviewmode' that stores the view mode
of the file picker element.

It was discussed whether handling of this preference should be added
here into core_form, or rather into core_repository subsystem. The final
decision was to consider the preference as owned by the core_form
because it is affecting the display of a form element, not the
repository backend (even though the strings describing it had been put
into core_repository strings).
2018-05-03 19:06:50 +02:00
Andrew Nicols b618310364 Merge branch 'MDL-62240-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-03 19:06:33 +08:00
Jake Dallimore 4b51386d9a Merge branch 'MDL-62310-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-05-03 18:04:46 +08:00
Jun Pataleta 08f2b6063f Merge branch 'MDL-61194-33' of git://git.cameron1729.xyz/moodle into MOODLE_33_STABLE 2018-05-03 17:06:00 +08:00
Cameron Ball b22bc26c51 MDL-61194 assignfeedback_editpdf: Check if we can convert online text
This patch adds a check to make sure there is a converter available that
will be able to handle html->pdf conversion before adding onlinetext
submissions to the list of files to combine.
2018-05-03 16:47:37 +08:00
Mihail Geshoski 044656f96a MDL-62046 profilefield_textarea: Add privacy files and unit tests 2018-05-03 16:28:48 +08:00
David Monllao 0612aa3418 Merge branch 'MDL-61693-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-05-03 10:25:03 +02:00
Andrew Nicols c73a9d5cbe MDL-61407 privacy: Reset the writer after writer tests
The writer was not reset after these tests which had the potential to
affect the next test after these were run.
2018-05-03 16:14:37 +08:00
Andrew Nicols 07049468e6 MDL-61407 quizaccess: Add null_writer implementations 2018-05-03 16:14:36 +08:00
Andrew Nicols 0a8a57943c MDL-61407 quiz: Add reports for quiz 2018-05-03 16:14:36 +08:00
Andrew Nicols 9c9d3ab247 MDL-61407 qtype: Add null_writer for all qtypes 2018-05-03 16:14:35 +08:00
Andrew Nicols 1b03a7f54d MDL-61407 qformat: Add null_writer for all qformats
Questions formats do not store any personal data.
Any contrib format which does store personal data should utilise the
standard export interfaces as this subsystem will not call them directly.
2018-05-03 16:14:35 +08:00
Andrew Nicols a6a8ecc369 MDL-61407 question: Add null_writer for all behaviours
Behaviours do not store any personal data.
Any contrib behaviour which does store personal data should utilise the
standard export interfaces as this subsystem will not call them directly.
2018-05-03 16:14:34 +08:00
Andrew Nicols 84b5f665ee MDL-61407 mod_quiz: Add initial privacy implementation 2018-05-03 16:14:34 +08:00
Andrew Nicols 5b2b0e66c1 MDL-61407 question: Add initial privacy implementation 2018-05-03 16:14:34 +08:00
David Monllao 03d182e726 Merge branch 'MDL-62059-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-05-03 10:08:24 +02:00
Mihail Geshoski 79380f1408 MDL-62032 profilefield_text: Add privacy files and unit tests 2018-05-03 16:05:33 +08:00
Mihail Geshoski f1034de3af MDL-62030 profilefield_menu: Add privacy files and unit tests 2018-05-03 15:54:40 +08:00
Mihail Geshoski 0756be091c MDL-62007 profilefield_checkbox: Modify privacy provider 2018-05-03 15:31:38 +08:00
Mihail Geshoski 3ec3295ae1 MDL-62007 profilefield_datetime: Add privacy files and unit tests 2018-05-03 15:24:24 +08:00
Sara Arjona 9543ced2b4 MDL-62240 privacy: Avoid error when path is higher than allowed
A new method shorten_filenames has been added to moodlelib.
2018-05-03 09:17:56 +02:00
Andrew Nicols 61140b097b MDL-62240 file: Add includehash to shorten_filename + unit tests 2018-05-03 08:33:01 +02:00
Jake Dallimore 40e33083b7 Merge branch 'MDL-62264-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-05-03 14:08:39 +08:00
Jun Pataleta e916aa4ae3 Merge branch 'MDL-62202-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-03 13:31:39 +08:00
Andrew Nicols 0202ab0473 Merge branch 'MDL-62009-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-05-03 12:36:18 +08:00
Andrew Nicols bce56f5031 Merge branch 'wip-MDL-62312-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-03 11:11:55 +08:00
Jake Dallimore e98ad2ad05 Merge branch 'MDL-62280-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-03 10:53:54 +08:00
Marina Glancy 74a3c0a49a MDL-62312 course: Move core_publish renderer methods to course renderer 2018-05-03 10:09:13 +08:00
Jun Pataleta 3618a1a90d Merge branch 'MDL-60414-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-05-03 09:31:14 +08:00
AMOS bot 1b6af94da4 Automatically generated installer lang files 2018-05-03 00:06:43 +00:00
Andrew Nicols 7597722505 MDL-61407 question: Allow formatters to ignore caps 2018-05-03 07:29:05 +08:00
Andrew Nicols f9f59314e9 MDL-61407 privacy: Track changes in any context 2018-05-03 07:29:05 +08:00
Jun Pataleta c66ec12365 MDL-62312 admin: Move core_register renderer methods to admin renderer
* Plus CI fixes
2018-05-03 06:53:00 +08:00
Luca Bösch 4099ae4896 MDL-60414 theme_boost: bootstrap dropdown menu html spec char rendering 2018-05-02 23:03:33 +02:00
cescobedo 23e11831bf MDL-62310 core_admin: Implement Privacy API 2018-05-02 12:02:36 +02:00
Andrew Nicols acd75c858e MDL-62135 tool_log: Use plugintype_class_callback 2018-05-02 17:48:17 +08:00
Andrew Nicols 78404d4134 Merge branch 'MDL-62135-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-05-02 17:47:59 +08:00
cescobedo 9abf9488e1 MDL-62264 core_mnet: Implement Privacy API 2018-05-02 11:23:07 +02:00
Frédéric Massart 5881e25d35 MDL-62135 logstore_legacy: Implement privacy API 2018-05-02 17:17:47 +08:00
Frédéric Massart e8861b846e MDL-62135 logstore_database: Implement privacy API 2018-05-02 17:17:47 +08:00
Frédéric Massart f37406011f MDL-62135 logstore_standard: Implement privacy API 2018-05-02 17:17:46 +08:00
Frédéric Massart 8ff7363219 MDL-62135 tool_log: Implement privacy API 2018-05-02 17:17:46 +08:00
David Mudrák 4f7b3cb360 MDL-61905 workshop: Drop the old 1.x era tables
These tables may still contain relics of old personal data if the site
was installed before Moodle 2.0. We do not need these tables any more.
Following the "privacy by design" principles, we are dropping them now.
2018-05-02 11:17:41 +02:00
Sara Arjona 196d9c90f3 MDL-62202 privacy: Move Privacy and policies category to Users page 2018-05-02 08:46:28 +02:00
Jun Pataleta fbafd55731 Merge branch 'MDL-62253-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-05-02 13:52:51 +08:00
Jun Pataleta 103c72a03a Merge branch 'MDL-61898-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-05-02 13:46:31 +08:00
Frédéric Massart 4352cd98bf MDL-62214 tool_messageinbound: False negative due to time() usage
PHP Unit is so fast that my test couldn't cope with it!
2018-05-02 13:10:13 +08:00
Andrew Nicols ebe14385a9 Merge branch 'MDL-61920_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-05-02 13:07:05 +08:00
Andrew Nicols 5648cec536 Merge branch 'MDL-62266-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-05-02 12:34:58 +08:00
Andrew Nicols f80f15a178 Merge branch 'MDL-62214-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-05-02 12:29:50 +08:00
Andrew Nicols 6a763870e0 MDL-61800 task: Reset the OUTPUT and PAGE on execution 2018-05-02 11:57:38 +08:00
Andrew Nicols 70ebf686fd Merge branch 'MDL-62236-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-05-02 10:55:00 +08:00
Andrew Nicols 0153ce4fad MDL-59845 tool_lp: Add js tracking around UI refresh 2018-05-02 09:18:21 +08:00
Eloy Lafuente (stronk7) 4d1c53e490 weekly release 3.3.5+ 2018-05-01 23:04:14 +02:00
Eloy Lafuente (stronk7) 7e968c33f8 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-05-01 23:04:12 +02:00
Frédéric Massart cb1ec4e3c7 MDL-62167 core_badges: Remove usage of a reserved keyword of Oracle 2018-05-01 15:23:00 +02:00
Frédéric Massart 0318b526f9 MDL-62167 core_badges: Prevent SQL error with Oracle 2018-05-01 15:22:59 +02:00
Andrew Nicols 2cff7ff95f Merge branch 'wip-MDL-61308-33-testfix' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-05-01 12:41:47 +02:00
Adrian Greeve 4bd2ccd63b MDL-61308 assignsubmission_comments: Unit test ordering fix. 2018-05-01 12:41:37 +02:00
Andrew Nicols 40b9237b49 Merge branch 'MDL-62231-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-05-01 12:41:26 +02:00
Andrew Nicols 6d780cde01 MDL-61898 cache: Implement privacy API for all stores and locks 2018-05-01 12:53:37 +08:00
Shamim Rezaie d6b5be41d4 MDL-62231 block_recent_activity: Implement null provider for the block 2018-05-01 14:08:46 +10:00
Andrew Nicols 0ef3ff5b68 Merge branch 'wip-MDL-62138-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-05-01 11:57:54 +08:00
Andrew Nicols ff6db243c0 Merge branch 'MDL-61411-33' of git://github.com/Kathrin84/moodle into MOODLE_33_STABLE 2018-05-01 11:24:47 +08:00
Andrew Nicols 515f4ea924 Merge branch 'MDL-62167-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-05-01 11:15:12 +08:00
Andrew Nicols 17d02fc2a8 MDL-62280 xhprof: Support tideways_xhprof 2018-05-01 11:03:16 +08:00
Frédéric Massart c9a9c02374 MDL-62009 core_grades: Implement privacy API 2018-05-01 10:50:13 +08:00
Jun Pataleta 01ad8ce22f Merge branch 'MDL-62060-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-05-01 10:44:46 +08:00
Shamim Rezaie afa0d54934 MDL-62060 core_privacy: Make sure the exported json is human readable 2018-05-01 12:36:55 +10:00
Frédéric Massart 53f5e8a321 MDL-62214 tool_messageinbound: Implement privacy API 2018-05-01 09:23:01 +08:00
Frédéric Massart 886191944f MDL-62214 tool_messageinbound: Delete old messages pending verification 2018-05-01 09:22:45 +08:00
Frédéric Massart a7abfcef0e MDL-62253 core_auth: Implement privacy API 2018-05-01 09:14:39 +08:00
Jake Dallimore 2aa7deb2f0 Merge branch 'MDL-62005-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-05-01 09:10:56 +08:00
AMOS bot 6d67378c41 Automatically generated installer lang files 2018-05-01 00:07:17 +00:00
Jun Pataleta ed7e2d03f0 Merge branch 'MDL-62248-33-fix' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-30 21:25:22 +08:00
Andrew Nicols 835a653755 MDL-62248 core_privacy: Add getter for user context prefs 2018-04-30 20:37:38 +08:00
Mark Nelson 149f1ecabd MDL-61920 mod_lti: implement privacy provider 2018-04-30 19:59:54 +08:00
Mark Nelson eb16feff78 MDL-61920 ltiservice_toolsettings: implement privacy provider 2018-04-30 19:02:18 +08:00
Mark Nelson 4c65cc4464 MDL-61920 ltiservice_toolproxy: implement privacy provider 2018-04-30 19:01:59 +08:00
Mark Nelson 249a14082e MDL-61920 ltiservice_profile: implement privacy provider 2018-04-30 19:01:40 +08:00
Mark Nelson 1c38c18ca1 MDL-61920 ltiservice_memberships: implement privacy provider 2018-04-30 19:01:19 +08:00
Jun Pataleta 7c44363a80 Merge branch 'MDL-61012_v3.3.x' of https://github.com/troywilliams/moodle into MOODLE_33_STABLE 2018-04-30 17:28:51 +08:00
Sara Arjona 2cc51e4887 MDL-62266 core_availability: Implement privacy API 2018-04-30 11:22:32 +02:00
Shamim Rezaie baffbd6d6f MDL-62005 block_comments: Add implementation of Privacy API 2018-04-30 18:16:45 +10:00
Andrew Nicols f0d0414a9e MDL-62248 core_privacy: Unit test for get_user_preferences 2018-04-30 16:03:43 +08:00
Andrew Nicols 774835181e Merge branch 'MDL-62248-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-30 16:02:33 +08:00
Frédéric Massart d1caad9938 MDL-62248 core_block: Implement privacy API 2018-04-30 15:30:18 +08:00
Frédéric Massart c08b4f9466 MDL-62248 core_privacy: Test writer writes user prefs in right contexts 2018-04-30 15:29:37 +08:00
Andrew Nicols 5d22d5087a MDL-61898 core_cache: Implement Privacy API 2018-04-30 14:25:36 +08:00
Shamim Rezaie 835f7f20da MDL-62059 mod_book: Implement null provider for mod_book 2018-04-30 16:16:48 +10:00
Andrew Nicols 69943f974b Merge branch 'MDL-62235-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-30 14:01:51 +08:00
Andrew Nicols 37427de44e Merge branch 'MDL-62208-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-30 13:21:09 +08:00
Troy Williams 3d9d924be6 MDL-61012 course: Allow extending class to set 2018-04-30 16:26:09 +12:00
Andrew Nicols be2d84d913 Merge branch 'MDL-62241-33-typehint' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-04-30 11:45:41 +08:00
Andrew Nicols ee5530d552 Merge branch 'MDL-61959-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-30 10:26:04 +08:00
Andrew Nicols f303211548 MDL-61308 mod_assign: Whitespace fix 2018-04-30 09:27:25 +08:00
Andrew Nicols ca427f5389 Merge branch 'wip-MDL-61308-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-30 09:22:30 +08:00
AMOS bot b40e466d20 Automatically generated installer lang files 2018-04-30 00:06:42 +00:00
Frédéric Massart 5bfaff81e7 MDL-62235 core_files: Implement privacy API 2018-04-29 10:17:35 +08:00
Frédéric Massart 80934c2385 MDL-62236 core_webservice: Implement privacy API 2018-04-29 10:10:19 +08:00
David Mudrák 8460b91e31 MDL-62241 privacy: Do not use scalar type hinting on 3.3 branch
The tests do not actually do anything, they just make sure that the
method signature is correct on the given PHP version.
2018-04-27 15:20:03 +02:00
Eloy Lafuente (stronk7) 1e65154616 weekly release 3.3.5+ 2018-04-27 13:15:33 +02:00
Eloy Lafuente (stronk7) 0d85f27c6f MDL-61993 profilefield_checkbox: take rid of oracle reserved word 2018-04-27 10:43:20 +02:00
Frédéric Massart 8391635fd9 MDL-61877 core_competency: Handle comments in privacy API 2018-04-27 11:30:19 +08:00
Frédéric Massart acf68b58cd MDL-61877 core_competency: Implement privacy API 2018-04-27 11:30:19 +08:00
Frédéric Massart e29ec14535 MDL-62167 core_badges: Implement privacy API 2018-04-27 10:51:26 +08:00
Bas Brands 486b512bc4 MDL-62172 Theme boostrapbase: align advanced checkbox in mform 2018-04-27 09:57:55 +08:00
Eloy Lafuente (stronk7) 46895a7b3d Merge branch 'MDL-60882-33' of git://github.com/jleyva/moodle into MOODLE_33_STABLE 2018-04-27 01:39:05 +02:00
Eloy Lafuente (stronk7) 520cc4e661 Merge branch 'wip_MDL-62011_33_approval_of_course_request' of https://github.com/grabs/moodle into MOODLE_33_STABLE 2018-04-27 01:30:36 +02:00
Eloy Lafuente (stronk7) eaecfd8d79 Merge branch 'MDL-61993-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-27 01:01:36 +02:00
Eloy Lafuente (stronk7) 7dbc822131 Merge branch 'MDL-61863-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-26 22:32:06 +02:00
Eloy Lafuente (stronk7) 86f3c6b22f Merge branch 'MDL-61715-33' of https://github.com/lethevinh/moodle into MOODLE_33_STABLE 2018-04-26 22:23:24 +02:00
Sara Arjona 079b45c562 MDL-61959 mod_scorm: Implement privacy API 2018-04-26 19:56:53 +02:00
Sara Arjona 81f4e778e8 MDL-61959 scormreport_objectives: Implement privacy API 2018-04-26 19:07:44 +02:00
sarjona bc1e9f0914 MDL-61959 scormreport_interactions: Implement privacy API 2018-04-26 19:07:15 +02:00
Sara Arjona 28d3ae01a6 MDL-61959 scormreport_graphs: Implement privacy API 2018-04-26 19:06:41 +02:00
sarjona d5a7132a6a MDL-61959 scormreport_basic: Implement privacy API 2018-04-26 19:06:09 +02:00
Jun Pataleta 0972a5bb7c Merge branch 'MDL-61986_33' of git://github.com/stronk7/moodle into MOODLE_33_STABLE 2018-04-27 00:46:26 +08:00
Eloy Lafuente (stronk7) 04a9173ac4 MDL-61986 mod_lesson: oracle order by clob fix 2018-04-26 18:32:18 +02:00
Eloy Lafuente (stronk7) 6b003a5bc1 Merge branch 'MDL-62224_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-04-26 17:38:46 +02:00
Zig Tan 8849300bd8 MDL-61693 core_calendar: Implemented privacy providers 2018-04-26 23:00:11 +08:00
Mark Nelson 9db1054919 MDL-62224 core_rss: implement correct provider 2018-04-26 20:17:15 +08:00
Kathrin Osswald 470a789ac2 MDL-61411 theme Boost: Close navigation on all items (on small screens) 2018-04-26 13:21:28 +02:00
Juan Leyva a760d1a278 MDL-61521 course: Add missing text formatting for category name 2018-04-26 12:38:34 +02:00
Juan Leyva b4665dba28 MDL-60882 mod_choice: Avoid teacher delete all responses
Teachers should be able to delete all responses but when indicating the
response ids.
When the response ids are not passed, only their own responses should
be deleted (as the function documentation said).
2018-04-26 10:26:29 +02:00
Adrian Greeve 7fceae553c MDL-61308 assign_feedback: Privacy code for user rights. 2018-04-26 15:41:59 +08:00
Adrian Greeve 8ab65b68b0 MDL-61308 assign_submission: Privacy code for user rights. 2018-04-26 15:41:58 +08:00
Adrian Greeve e637c48678 MDL-61308 mod_assign: Adding privacy classes. 2018-04-26 15:41:58 +08:00
Andrew Nicols a20987ace8 Merge branch 'wip-MDL-62215-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-26 15:01:11 +08:00
Andrew Nicols 4444333a28 Merge branch 'MDL-61947-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-26 14:52:55 +08:00
Adrian Greeve 001b73720d MDL-62215 core_privacy: Update to methods to remove type hinting. 2018-04-26 14:49:16 +08:00
Frédéric Massart fdd07c306a MDL-62208 core_fileconverter: Implement privacy API 2018-04-26 12:55:52 +08:00
Zig Tan 05807656a2 MDL-61947 core_my: Implemented privacy providers 2018-04-26 12:51:54 +08:00
Mihail Geshoski 27fa56c9f8 MDL-61993 profilefield_checkbox: Add privacy files and unit tests 2018-04-26 10:51:25 +08:00
Eloy Lafuente (stronk7) eb960618a1 Merge branch 'MDL-61979-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-26 03:09:44 +02:00
Eloy Lafuente (stronk7) 87aaec6c82 Merge branch 'MDL-61998-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-26 02:40:18 +02:00
Andrew Nicols 08339c2799 Merge branch 'MDL-61944-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-26 08:35:21 +08:00
Eloy Lafuente (stronk7) 2b33a8b518 Merge branch 'MDL-62181-33-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-04-25 19:09:59 +02:00
David Monllao ff36037e13 Merge branch 'MDL-62175-33' of git://github.com/jleyva/moodle into MOODLE_33_STABLE 2018-04-25 17:37:41 +02:00
David Monllao d38c995dcd Merge branch 'MDL-61986-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-25 16:32:56 +02:00
cescobedo f26b3692c5 MDL-61944 tool_mobile: Implement Privacy API 2018-04-25 15:39:27 +02:00
David Mudrák 9701aa1a6f MDL-62181 lang: Fix changed admin node title in behat scenario 2018-04-24 22:27:16 +02:00
Helen Foster 8a936e7371 MDL-62181 lang: Merge English strings from the en_fix language pack
Significant string changes:

* sitepolicies, core_admin - 'Site policies' changed to 'Site security
  settings'
* sitepolicy_help and sitepolicyguest_help, core_admin - setting will
  only have an effect if the site policy handler is set to default
* sitepolicyhandler_desc,core_admin - improved wording
* pathtodot_help, core_admin - Windows and Mac paths
* debugstringids_desc, core_admin - improved explanation
2018-04-24 22:26:34 +02:00
Eloy Lafuente (stronk7) 48ab35f25d weekly release 3.3.5+ 2018-04-24 18:57:16 +02:00
Juan Leyva e69580756c MDL-62175 auth_email: Fix site policy enabled check 2018-04-24 15:07:09 +02:00
vinhle 3c75559a6a MDL-61715 question: qbank_chooser is not intelligent about headings 2018-04-24 16:07:54 +07:00
Zig Tan 111f4da8e4 MDL-61863 core_notes: Implemented privacy providers 2018-04-24 12:11:22 +08:00
Jun Pataleta d03959c524 Merge branch 'MDL-62079-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-24 11:55:44 +08:00
Andrew Nicols 902f812c72 MDL-62079 core_filters: Implement null provider 2018-04-24 11:49:59 +08:00
Mark Nelson 9ede824794 MDL-62140 core_privacy: only reset tests when necessary 2018-04-24 11:16:58 +08:00
Frédéric Massart 21f51cf2a6 MDL-61984 mod_chat: Do not assume context passed is one of chat 2018-04-24 11:04:19 +08:00
Andrew Nicols 1dacf6193f MDL-62140 core_privacy: Improve unit test 2018-04-24 10:20:13 +08:00
Andrew Nicols 06e1ec0cf4 Merge branch 'MDL-62140_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-04-24 10:19:49 +08:00
Jun Pataleta 2be0984d4f Merge branch 'MDL-61764_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-04-24 09:54:01 +08:00
Jun Pataleta 9826b43f94 Merge branch 'MDL-61882-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-24 09:38:04 +08:00
Andrew Nicols 660d630ad5 Merge branch 'MDL-61984-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-24 09:34:53 +08:00
Andrew Nicols f203772256 Merge branch 'MDL-61995-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-24 08:21:33 +08:00
cescobedo 6675f08970 MDL-61882 auth_oauth2: Implement Privacy API 2018-04-23 19:35:51 +02:00
David Monllao b039e36e7e Merge branch 'MDL-61915-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-23 16:26:30 +02:00
David Monllao 11379b3995 Merge branch 'MDL-62042-m33' of https://github.com/sammarshallou/moodle into MOODLE_33_STABLE 2018-04-23 16:08:27 +02:00
cescobedo 184c8ddb25 MDL-61915 enrol: Add privacy implementation for all enrol plugins
None of the Enrol plugins (except lti and paypal) have any user preference or database table.
They all implement the null provider.
2018-04-23 14:25:49 +02:00
Mark Nelson b628cab84f MDL-62140 core_privacy: add helper functions to add system/user context 2018-04-23 20:08:22 +08:00
David Monllao bc67687abf MDL-62047 core_userkey: No return types in php 5.x 2018-04-23 13:09:18 +02:00
Andrew Nicols f9bbcab782 Merge branch 'wip-MDL-61759-33' of https://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-04-23 18:32:45 +08:00
David Monllao fae6020b32 Merge branch 'MDL-62078-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-23 12:09:06 +02:00
David Monllao e0de954728 Merge branch 'MDL-62047-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-23 11:59:42 +02:00
David Monllao 59fc010ac9 Merge branch 'MDL-61891-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-23 11:55:40 +02:00
Sara Arjona 54f5ded420 MDL-61998 cohort: Implement privacy API 2018-04-23 11:44:35 +02:00
Zig Tan e93d70e1c9 MDL-61995 tool_assignmentupgrade: Implemented privacy providers 2018-04-23 16:55:19 +08:00
Marina Glancy 2d6bc5cd57 MDL-61759 admin: non-existing site policy handler means no policy 2018-04-23 16:47:27 +08:00
Andrew Nicols 501dec0271 Merge branch 'MDL-62055-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-23 16:05:23 +08:00
Jun Pataleta dd0c7b7329 Merge branch 'MDL-62049_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-04-23 13:54:24 +08:00
Marina Glancy b7f7b588a3 MDL-62138 core: remove core_register and core_publish
These components have no classes and no strings and have no purspose. Component core_hub is responsible
for storing data, defining classes and strings for site registration and course publishing

This also reverts MDL-61945
2018-04-23 13:23:32 +08:00
Jun Pataleta c592b7529c Merge branch 'wip-MDL-61966-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-23 13:11:14 +08:00
Mark Nelson 47bad57184 MDL-62049 core_privacy: use correct lang string for date 2018-04-23 13:03:47 +08:00
Andrew Nicols 9a17f41506 MDL-61891 core_portfolio: Use manager method caller 2018-04-23 10:13:43 +08:00
Andrew Nicols e435e42e29 MDL-61891 core_plagiarism: Use manager method caller 2018-04-23 10:13:14 +08:00
Andrew Nicols 63a4554474 MDL-61891 privacy: Add helper to call methods on interfaces 2018-04-23 10:11:20 +08:00
Andrew Nicols 368436baac Merge branch 'MDL-61759-33-nonexistinghandler' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-04-22 21:06:41 +08:00
Frédéric Massart d3a7b1ff87 MDL-61986 mod_lesson: Implement privacy API 2018-04-22 17:32:14 +08:00
sarjona 616559742e MDL-62078 rss: Link to core_userkey in the Privacy API implementation 2018-04-22 09:05:41 +02:00
Andreas Grabs 0b1c63416f MDL-62011 course: Approval of a course request fails 2018-04-21 20:55:36 +02:00
Eloy Lafuente (stronk7) 7bd8cd00de weekly release 3.3.5+ 2018-04-20 23:52:07 +02:00
sam marshall 37acf2d4be MDL-62042 core_search: Unicode non-characters cause indexing problems
Unicode characters such as U+FFEF can be entered into Moodle data and
cause indexing failures. This change strips them out of search fields.
2018-04-20 12:24:31 +01:00
Sara Arjona c82e60d0f3 MDL-62055 imscp: Implement privacy API 2018-04-20 09:04:53 +02:00
Adrian Greeve 062c83aae2 MDL-61966 block_myoverview: Update to provider for user preferences. 2018-04-20 14:51:56 +08:00
Andrew Nicols ac3bb88f6f MDL-61958 core_rss: Remove type-hint for PHP 5.6 2018-04-20 12:25:27 +08:00
Mark Nelson 5f02dbb5fd MDL-61764 message_popup: implement privacy provider 2018-04-20 12:10:57 +08:00
Jun Pataleta 349d0b6772 Merge branch 'MDL-62048_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-04-20 11:53:21 +08:00
Andrew Nicols a55d5c8292 Merge branch 'MDL-61892-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-20 11:49:59 +08:00
Zig Tan a85d8cffc1 MDL-61892 admin/tools: Implement null privacy providers 2018-04-20 11:46:30 +08:00
Andrew Nicols 4caf14d0dc Merge branch 'wip-MDL-62035-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-20 11:36:19 +08:00
Adrian Greeve 5b9837e832 MDL-62035 core_blog: Update to blog with comments.
This makes blog use the updated delete methods in the
comments provider.
2018-04-20 10:52:05 +08:00
Adrian Greeve ed7c8cf849 MDL-62035 core_comment: Update to deletion methods.
Also clarification with the export method to clarify that it
is only for one context.
2018-04-20 10:51:51 +08:00
Andrew Nicols 6a76fdfa40 Merge branch 'MDL-62003-33-privacyfiles' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-04-20 10:43:54 +08:00
Jun Pataleta 36f4e4c861 Merge branch 'MDL-61848-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-20 09:19:35 +08:00
Andrew Nicols 10093c3635 MDL-61836 blog: Fix random order failures 2018-04-20 08:57:11 +08:00
Łukasz Szeremeta c9ef8771ce MDL-61827 auth: Change Facebook Graph API v2.8 to v.2.12 in OAuth2
Use v2.12 Facebook Graph API instead of v2.8
2018-04-20 02:33:55 +02:00
Eloy Lafuente (stronk7) 5f2fe216f0 Merge branch 'MDL-61836-33-fix' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-20 02:29:04 +02:00
Eloy Lafuente (stronk7) bf91ad7c8c Merge branch 'MDL-61991-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-04-20 02:25:10 +02:00
Eloy Lafuente (stronk7) be960b40a0 Merge branch 'MDL-61975-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-20 02:18:14 +02:00
Andrew Nicols 48037ff7b0 MDL-61836 comment: Add missing require 2018-04-20 08:17:59 +08:00
Eloy Lafuente (stronk7) a5ca61930d Merge branch 'MDL-61348-take2_33' of git://github.com/timhunt/moodle into MOODLE_33_STABLE 2018-04-20 02:02:15 +02:00
cescobedo fa334d3119 MDL-61848 auth_manual: Implement Privacy API 2018-04-20 00:28:40 +02:00
Andrew Nicols b71fc4ce4b Merge branch 'MDL-61836-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-19 20:37:33 +08:00
Frédéric Massart 113e66d70b MDL-61984 mod_chat: Implement privacy API 2018-04-19 17:33:14 +08:00
Frédéric Massart 297661d754 MDL-61836 core_blog: Prevent randomness in comments order 2018-04-19 16:07:09 +08:00
Mark Nelson e8112121d5 MDL-62025 mod_choice: add missing join on modules table 2018-04-19 15:52:42 +08:00
Andrew Nicols 6480c4091e MDL-62047 core_userkey: Add privacy implementation 2018-04-19 15:30:39 +08:00
Andrew Nicols b81b826c4a MDL-62047 core_userkey: Define component path 2018-04-19 15:26:09 +08:00
Andrew Nicols af1c644712 Merge branch 'MDL-61568-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-19 15:01:37 +08:00
Andrew Nicols 3a84788acf Merge branch 'MDL-61970-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-19 14:54:02 +08:00
Andrew Nicols 78ecf75ead Merge branch 'MDL-61969-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-19 14:49:44 +08:00
Jun Pataleta 721fd1795f Merge branch 'MDL-61878-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-19 14:39:55 +08:00
Zig Tan c92feb872d MDL-61568 repository_flickr: Fix oauth secret export 2018-04-19 14:39:47 +08:00
Mihail Geshoski b7844952d7 MDL-61878 fileconverter_googledrive: Add privacy files and unit tests 2018-04-19 13:20:50 +08:00
Frédéric Massart 34d73b6faa MDL-61970 mod_survey: Do not assume context passed is one of survey 2018-04-19 13:12:48 +08:00
Mark Nelson cb4f59d780 MDL-62048 core_privacy: extend test to ensure table exists 2018-04-19 13:04:11 +08:00
Andrew Nicols 521751de69 Merge branch 'MDL-61945-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-19 11:56:32 +08:00
Andrew Nicols c813b07254 Merge branch 'MDL-61948-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-19 11:47:50 +08:00
Andrew Nicols 399252fd85 Merge branch 'MDL-61836-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-19 11:22:07 +08:00
Andrew Nicols bdbe55c831 Merge branch 'MDL-61970-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-19 11:13:53 +08:00
David Monllao 7ff43c2334 Merge branch 'MDL-61716-33' of git://github.com/mastnym/moodle into MOODLE_33_STABLE 2018-04-18 17:40:10 +02:00
David Monllao 35b09d5623 MDL-61958 rss: Add rss test suite 2018-04-18 17:38:28 +02:00
David Monllao 9073a4e708 Merge branch 'MDL-61958-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-18 17:22:40 +02:00
David Mudrák f3a972d97a MDL-62003 privacy: Consistently export files into _files folder
There were two major issues with the previous implementation:

* The exported folder name was localised so it was "Files" or "Soubory"
  etc depending on the current language. Yet URLs referring to the files
  in that folder were always rewritten with hard-coded English "files".
* Files from all fileareas and itemids were all exported to a single
  target directory. So if there were two files with the same name being
  exported from multiple areas (such as submission_content and
  submission_attachment in the workshop module), one would overwrite
  another.

The patch addresses these issues as follows:

* To unify the folder name and also to minimise the risk of conflict
  with a subcontext folder, we now always export stored files under
  "_files" folder.
* Under that folder, there is a subdirectory with the area name and then
  eventually another subdirectory with non-zero itemid. And there
  finally the stored_file is exported to under its own file path.
2018-04-18 17:08:16 +02:00
Martin Mastny 8b58e0535c MDL-61716 auth_oauth2: field names in mappings allow all characters 2018-04-18 16:54:45 +02:00
David Monllao dced5c43c8 Merge branch 'MDL-38099-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-04-18 14:14:55 +02:00
Sara Arjona 7ce30dda42 MDL-61958 core_rss: Implement privacy API 2018-04-18 13:38:00 +02:00
Eloy Lafuente (stronk7) 5c4ff2db85 Merge branch 'MDL-61621_33' of git://github.com/dmonllao/moodle into MOODLE_33_STABLE 2018-04-18 12:58:59 +02:00
Jun Pataleta 31d0fb4349 Merge branch 'MDL-62025_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-04-18 16:25:43 +08:00
Jun Pataleta a2155a12e4 Merge branch 'MDL-61928_33' of git://github.com/timhunt/moodle into MOODLE_33_STABLE 2018-04-18 16:00:21 +08:00
Mark Nelson 774108ca8a MDL-62025 mod_choice: only export in the CONTEXT_MODULE context 2018-04-18 15:12:37 +08:00
Frédéric Massart c9ca50d029 MDL-61970 mod_survey: Implement privacy API 2018-04-18 14:56:31 +08:00
Andrew Nicols 5298471d0f Merge branch 'MDL-61568-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-18 14:26:01 +08:00
Mihail Geshoski 22f6afdcd5 MDL-61969 datapreset_imagegallery: Implement null privacy provider 2018-04-18 13:51:35 +08:00
Zig Tan 0a617a7e20 MDL-61568 core_repository: Implement privacy providers 2018-04-18 13:49:33 +08:00
Zig Tan 73f8e3dc26 MDL-61568 repository_onedrive: Implement privacy providers 2018-04-18 13:49:33 +08:00
Zig Tan 709350d111 MDL-61568 repository_youtube: Implement privacy providers 2018-04-18 13:49:33 +08:00
Zig Tan 8186a5994d MDL-61568 repository_wikimedia: Implement privacy providers 2018-04-18 13:49:27 +08:00
Zig Tan 70698f7964 MDL-61568 repository_picasa: Implement privacy providers 2018-04-18 13:47:56 +08:00
Zig Tan ecebec32bc MDL-61568 repository_merlot: Implement privacy providers 2018-04-18 13:47:56 +08:00
Zig Tan 5b0ae8c97d MDL-61568 repository_googledocs: Implement privacy providers 2018-04-18 13:47:56 +08:00
Zig Tan ce52426d52 MDL-61568 repository_flickr_public: Implement privacy providers 2018-04-18 13:47:56 +08:00
Zig Tan a00de36d15 MDL-61568 repository_flickr: Implement privacy providers 2018-04-18 13:47:44 +08:00
Mihail Geshoski 0f4c592b5c MDL-61948 core_media: Implement null privacy provider 2018-04-18 13:44:30 +08:00
Jun Pataleta 07f6d8962c Merge branch 'MDL-61520-33' of git://github.com/lameze/moodle into MOODLE_33_STABLE 2018-04-18 13:28:12 +08:00
Andrew Nicols 132ea1c052 Merge branch 'MDL-61957-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-18 13:10:34 +08:00
Zig Tan 9f2f2294d8 MDL-61979 tool_cohortroles: Implemented privacy providers 2018-04-18 10:55:05 +08:00
Eloy Lafuente (stronk7) c873339cc1 Merge branch 'm33_MDL-59857' of https://github.com/danmarsden/moodle into MOODLE_33_STABLE 2018-04-18 03:08:35 +02:00
Luca Bösch a5dddf9bff MDL-61991 theme_boost: Question correctness displayed as label. 2018-04-17 22:38:24 +02:00
Luca Bösch 9152286263 MDL-38099 comments: year in comments date 2018-04-17 22:37:33 +02:00
Eloy Lafuente (stronk7) 3e3a083ed1 weekly release 3.3.5+ 2018-04-17 19:54:34 +02:00
Eloy Lafuente (stronk7) a879012464 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-04-17 19:54:32 +02:00
Sara Arjona 18b98348a9 MDL-61957 gradereport_user: Implement privacy API 2018-04-17 14:48:04 +02:00
Sara Arjona caeb922dea MDL-61957 gradereport_singleview: Implement privacy API 2018-04-17 14:47:19 +02:00
Sara Arjona f79f0b5975 MDL-61957 gradereport_overview: Implement privacy API 2018-04-17 14:46:35 +02:00
Sara Arjona 6b8921a67b MDL-61957 gradereport_outcomes: Implement privacy API 2018-04-17 14:45:55 +02:00
Sara Arjona 01dd8aff46 MDL-61957 gradereport_history: Implement privacy API 2018-04-17 14:45:14 +02:00
Sara Arjona f4c5e78107 MDL-61957 gradereport_grader: Implement privacy API 2018-04-17 14:44:30 +02:00
Andrew Nicols 019a88a178 MDL-61663 phpunit: Add portfolio to the testsuite list 2018-04-17 14:45:04 +08:00
cescobedo ef66a33a94 MDL-61945 core_register: Implement Privacy API 2018-04-17 08:26:26 +02:00
Jun Pataleta 6411b74074 Merge branch 'MDL-61862-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-17 12:04:20 +08:00
Andrew Nicols 3b8ee4c3a0 Merge branch 'wip-MDL-61663-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-17 11:46:58 +08:00
Adrian Greeve a3a7a072e1 MDL-61663 portfolio: Update to the external system link names.
Changed the name of the link to something less like an English
string for each of the portfolios.
2018-04-17 11:44:10 +08:00
Andrew Nicols db1a3e6623 Merge branch 'MDL-61977-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-17 11:43:32 +08:00
Frédéric Massart 739507da50 MDL-61862 mod_feedback: Tweak query to support UNION on TEXT fields
Thanks Oracle.
2018-04-17 11:36:55 +08:00
Andrew Nicols ace39db60f Merge branch 'MDL-61980-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-17 11:35:37 +08:00
Andrew Nicols 4dd2d6a7e0 Merge branch 'MDL-61916-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-17 11:19:40 +08:00
Zig Tan 1414c0c83a MDL-61568 repository_dropbox: Implement privacy providers 2018-04-17 11:16:58 +08:00
Zig Tan 9fd2c9c529 MDL-61568 repository_boxnet: Implement privacy providers 2018-04-17 11:14:50 +08:00
Andrew Nicols d405b3b89a Merge branch 'MDL-61918-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-17 11:13:16 +08:00
Zig Tan 65f6e6ad89 MDL-61568 repository_webdav: Implement null privacy provider 2018-04-17 11:12:59 +08:00
Zig Tan 948d3f566f MDL-61568 repository_user: Implement null privacy provider 2018-04-17 11:11:22 +08:00
Andrew Nicols 8cd3227cd4 Merge branch 'MDL-61903-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-17 11:10:36 +08:00
Zig Tan a5947dc4cc MDL-61568 repository_url: Implement null privacy provider 2018-04-17 11:10:21 +08:00
Zig Tan b767d92456 MDL-61568 repository_upload: Implement null privacy provider 2018-04-17 11:08:37 +08:00
Zig Tan 208a7c059f MDL-61568 repository_skydrive: Implement null privacy provider 2018-04-17 11:07:09 +08:00
Zig Tan bbaea992ab MDL-61568 repository_s3: Implement null privacy provider 2018-04-17 11:06:07 +08:00
Zig Tan 6b318d7f2b MDL-61568 repository_recent: Implement null privacy provider 2018-04-17 11:04:44 +08:00
Zig Tan 3656528c45 MDL-61568 repository_local: Implement null privacy provider 2018-04-17 11:03:35 +08:00
Zig Tan 80ba17b0a5 MDL-61568 repository_filesystem: Implement null privacy provider 2018-04-17 11:02:21 +08:00
Zig Tan fe9954ef1f MDL-61568 repository_equella: Implement null privacy provider 2018-04-17 11:00:56 +08:00
Zig Tan b94fe0ece2 MDL-61568 repository_coursefiles: Implement null privacy provider 2018-04-17 10:59:52 +08:00
Zig Tan c585e4fc60 MDL-61568 repository_areafiles: Implement null privacy provider 2018-04-17 10:58:36 +08:00
Mihail Geshoski e217c239fd MDL-61903 webservice: Implement null privacy provider
Implement null privacy provider to rest, soap and xmlrpc webservice plugins.
2018-04-17 09:21:19 +08:00
Dan Marsden bdb5843290 MDL-59857 mod_scorm: use valid length for grade type field. 2018-04-17 08:44:50 +12:00
Jun Pataleta 2eb7414d52 Merge branch 'MDL-61862-33-56' of git://github.com/FMCorz/moodle into MOODLE_33_STABLE 2018-04-16 23:29:50 +08:00
Eloy Lafuente (stronk7) 225408d744 MDL-61819 editor: add testsuite to phpunit.xml 2018-04-16 16:38:58 +02:00
David Monllao 07fa93a0ec Merge branch 'MDL-61819-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-16 16:15:29 +02:00
Andrew Nicols 86feef9a01 MDL-61819 core_editor: Implement core provider 2018-04-16 21:54:32 +08:00
Andrew Nicols d885504581 MDL-61819 editor_atto: Implement null provider 2018-04-16 21:54:32 +08:00
Andrew Nicols 1e9ba15782 MDL-61819 editor: Implement editor null providers 2018-04-16 21:54:07 +08:00
Frédéric Massart e07927711e MDL-61862 mod_feedback: Implement core_privacy API 2018-04-16 18:47:14 +08:00
David Monllao 1ff3c3a64c Merge branch 'MDL-61741-33-paypal' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-04-16 10:59:04 +02:00
David Monllao 933afbd395 Merge branch 'wip-MDL-61808-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-16 10:04:09 +02:00
Jun Pataleta 0fc22245e1 Merge branch 'MDL-61708-MOODLE33-lti-fullnamedisplay' of https://github.com/wjroes/moodle into MOODLE_33_STABLE 2018-04-16 15:29:52 +08:00
Sara Arjona 81ea58cdf5 MDL-61958 rss: Create core_rss lang file and move rss string
At the moment will only be copied one of the rss strings ('rss').
The issue MDL-61997 has been created to move the rest of the core_rss lang
strings from moodle.php to rss.php.

AMOS BEGIN
 CPY [rss,core],[rss,core_rss]
AMOS END
2018-04-16 09:17:52 +02:00
Sara Arjona 0682576b8e MDL-61958 lang: Move privatefilesmanage string to correct place 2018-04-16 09:17:52 +02:00
Jun Pataleta 4a12d7a081 Merge branch 'MDL-61974-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-16 13:16:11 +08:00
Andrew Nicols 517baef479 MDL-61974 privacy: Rewrite the content writer storage 2018-04-16 11:11:47 +08:00
Andrew Nicols b88a6ac832 Merge branch 'MDL-61952-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-16 10:52:15 +08:00
Andrew Nicols 4ccebf873e Merge branch 'MDL-61954-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-04-16 10:47:35 +08:00
Andrew Nicols bc77389997 Merge branch 'MDL-61902-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-16 10:22:10 +08:00
Mihail Geshoski fbf8d40f98 MDL-61918 assignment: Implement null privacy provider
Implement null privacy provider to offline, online, upload and uploadsingle assignment plugins.
2018-04-16 10:03:25 +08:00
Mihail Geshoski 0c8d774cba MDL-61902 media: Implement null privacy provider 2018-04-16 09:48:32 +08:00
AMOS bot 51b7c14545 Automatically generated installer lang files 2018-04-16 00:07:30 +00:00
Adrian Greeve 396fe24044 MDL-61808 tool_monitor: Implemented privacy classes.
This plugin is now compatible with the new privacy system.
2018-04-14 10:57:28 +08:00
Mihail Geshoski 7b9251eb7f MDL-61980 booktool: Implement null privacy provider
Implement null privacy provider into booktool_exportimscp, booktool_importhtml, booktool_print plugin.
2018-04-13 16:20:49 +08:00
David Mudrák 5f9e43efaa MDL-61759 admin: Fix notice if attempting use nonexisting policy handler
The list of all known handlers may not contain the configured value,
raising the PHP undefined index notice.
2018-04-13 10:00:34 +02:00
Jake Dallimore 1568fc669c MDL-61663 portfolio_picasa: add privacy provider implementation 2018-04-13 14:49:57 +08:00
Jake Dallimore 3a3abbbbd8 MDL-61663 portfolio_googledocs: add privacy provider implementation 2018-04-13 14:49:56 +08:00
Jake Dallimore ca50317233 MDL-61663 portfolio_flickr: add privacy provider implementation 2018-04-13 14:49:56 +08:00
Jake Dallimore b8bea9d1b7 MDL-61663 portfolio_download: add privacy provider implementation 2018-04-13 14:49:56 +08:00
Jake Dallimore a4535a6511 MDL-61663 portfolio_boxnet: add privacy provider implementation 2018-04-13 14:49:56 +08:00
Jake Dallimore f5579a67d8 MDL-61663 portfolio_mahara: add privacy provider implementation 2018-04-13 14:49:55 +08:00
Jake Dallimore ff0e438780 MDL-61663 core_portfolio: add subsystem privacy provider
Added provider for portfolio plugins, and legacy polyfill for plugins.
2018-04-13 14:49:54 +08:00
Zig Tan f9d9e29861 MDL-61977 tool_profiling: Implemented null privacy provider 2018-04-13 14:40:42 +08:00
Zig Tan c4b7e6de55 MDL-61975 tool_recyclebin: Implemented null privacy provider 2018-04-13 13:59:42 +08:00
Frédéric Massart 6275657518 MDL-61836 core_blog: Implement privacy API 2018-04-13 13:31:22 +08:00
David Monllao e1ed5f7ae4 weekly release 3.3.5+ 2018-04-12 14:38:19 +02:00
David Monllao 5204900673 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-04-12 14:38:18 +02:00
Sara Arjona a2a91c1fcf MDL-61954 gradeimport_xml: Implement privacy API 2018-04-12 09:57:57 +02:00
Sara Arjona 5ae13d00c0 MDL-61954 gradeimport_direct: Implement privacy API 2018-04-12 09:57:27 +02:00
Sara Arjona 2c746ce80a MDL-61954 gradeimport_csv: Implement privacy API 2018-04-12 09:56:43 +02:00
Sara Arjona a79e82588d MDL-61952 gradeexport_xml: Implement privacy API 2018-04-12 08:32:30 +02:00
Sara Arjona 0405156624 MDL-61952 gradeexport_xls: Implement privacy API 2018-04-12 08:32:16 +02:00
Sara Arjona a8f19ad776 MDL-61952 gradeexport_txt: Implement privacy API 2018-04-12 08:31:35 +02:00
Sara Arjona 9de64f724e MDL-61952 gradeexport_ods: Implement privacy API 2018-04-12 08:31:07 +02:00
nlnrose cb411703b7 MDL-61802 Admin: Corrected typo in test file.
The file privcacy_provider_test.php was supposed to be
privacy_provider_test.php.
2018-04-12 00:24:09 +02:00
Eloy Lafuente (stronk7) 6477811c56 Merge branch 'MDL-61828-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-12 00:14:57 +02:00
Eloy Lafuente (stronk7) 0103da4a97 Merge branch 'MDL-61895-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-11 23:58:34 +02:00
Eloy Lafuente (stronk7) 1475e116df Merge branch 'MDL-61896-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-11 23:55:14 +02:00
David Monllao e0228935e4 MDL-61743 message: Add context level checking 2018-04-11 19:32:31 +02:00
David Monllao b43a5dd313 MDL-61743 core_privacy: Add context level checks for all users deletion 2018-04-11 19:32:26 +02:00
Andrew Nicols 9c68283112 MDL-61743 core_privacy: Reduce context specificty
Deletion is called for a context against all components, not just
modules.
2018-04-11 19:32:08 +02:00
David Monllao 8cb537ec1b Merge branch 'MDL-61873-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-11 18:42:09 +02:00
David Monllao 2e980b6b3a Merge branch 'MDL-61581-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-04-11 18:08:10 +02:00
Jake Dallimore 1c93fc9444 Merge branch 'MDL-59691-33' of https://github.com/lucisgit/moodle into MOODLE_33_STABLE 2018-04-11 16:02:31 +08:00
Simey Lameze 5155bf10bc MDL-61520 quiz: fix references for xhtml on stats report 2018-04-11 10:49:45 +08:00
Andrew Nicols 1a83ee366d Merge branch 'MDL-61881-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-11 10:16:24 +08:00
Zig Tan cd0173d077 MDL-61881 report: fix privacy lang strings 2018-04-11 10:12:23 +08:00
Andrew Nicols 9280d2ca0b Merge branch 'MDL-61731-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-11 09:12:51 +08:00
Mihail Geshoski ee49ade9c9 MDL-61731 message_email: Add privacy files and unit tests 2018-04-11 09:08:19 +08:00
Andrew Nicols 1eaf0be6ed Merge branch 'MDL-61867-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-11 08:52:42 +08:00
AMOS bot 7c46fbea90 Automatically generated installer lang files 2018-04-11 00:07:34 +00:00
Tim Hunt 5d307557cb MDL-61928 formslib: shortforms should work with non-editable forms 2018-04-10 17:40:25 +01:00
Tim Hunt 24d2357da7 MDL-61348 quiz reports: fix incorrect groups averages
the averages were wrong if a user had mulitple enrolments in a course,
which can happen with some enrolment plugins.
2018-04-10 17:12:09 +01:00
Eloy Lafuente (stronk7) 00cb9fe1e1 Merge branch 'wip-MDL-58697-33-assigngrading' of git://github.com/adamann2/moodle into MOODLE_33_STABLE 2018-04-10 15:54:26 +02:00
David Monllao fd772ad29a Merge branch 'MDL-61838-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-10 13:44:28 +02:00
David Monllao 84f821c5c8 Merge branch 'MDL-61843-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-10 13:42:57 +02:00
Eloy Lafuente (stronk7) dd5039e55d MDL-61875 tests: Use existing component & support $CFG->admin 2018-04-10 13:12:14 +02:00
Eloy Lafuente (stronk7) 6e5876ca57 Merge branch 'MDL-61875-33' of https://github.com/snake/moodle into MOODLE_33_STABLE 2018-04-10 13:06:53 +02:00
David Monllao 8392c88414 Merge branch 'MDL-61846-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-10 08:59:45 +02:00
David Monllao fddf02e152 Merge branch 'MDL-61129-fix-accessibility-on-tables-mod_survey_Moodle-33' of https://github.com/guillalva06/moodle into MOODLE_33_STABLE 2018-04-10 07:59:22 +02:00
Andrew Nicols 94714224d9 Merge branch 'MDL-61795-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-10 10:58:15 +08:00
Mihail Geshoski e17623068c MDL-61795 block_rss_client: Add privacy files and unit tests 2018-04-10 09:42:33 +08:00
Jake Dallimore 0ccecc5f49 MDL-61875 core_privacy: update the core_component_list in the manager 2018-04-10 08:52:01 +08:00
Jake Dallimore 3ad05e0471 MDL-61875 core_component: new method to get full components list 2018-04-10 08:51:59 +08:00
Eloy Lafuente (stronk7) bc3e7588b9 Merge branch 'MDL-61860-33' of https://github.com/mackensen/moodle into MOODLE_33_STABLE 2018-04-10 01:01:17 +02:00
Eloy Lafuente (stronk7) 61ab947bd1 Merge branch 'MDL-60196_33' of https://github.com/mfabriczy/moodle into MOODLE_33_STABLE 2018-04-10 00:57:46 +02:00
cescobedo 6757aa403e MDL-61916 format: Add privacy implementation for all format plugins
None of the Course format plugins have any user preference or database table.
They all implement the null provider.
2018-04-10 00:31:12 +02:00
Daniel Thies f9c68b4a4d MDL-61476 mod_glossary: Check XML arrays exist 2018-04-09 23:47:34 +02:00
Daniel Thies ff9019a16b MDL-61476 mod_glossary: Support tags in entries export 2018-04-09 23:47:26 +02:00
Eloy Lafuente (stronk7) 3857876a58 Merge branch 'MDL-61861-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-09 20:30:41 +02:00
Tony Butler 3eef55dda4 MDL-59691 assignfeedback_editpdf: Allow comment placement to all edges
Plus a couple of extra usability improvements:
- Collapse comment during move to allow precise placement
- Change cursor style to indicate that dragging is possible
2018-04-09 16:56:35 +01:00
Tony Butler 8531f802ec MDL-59691 assignfeedback_editpdf: Allow comments to collapse to top-left
Forcing them to collapse to the bottom-left corner seems less natural
and effectively changes the location of existing comments from pre-3.3
2018-04-09 16:56:35 +01:00
Guillermo Alvarez 77e0eaf2a6 MDL-61129 survey: Add colgroup attribute at survey question tables 2018-04-09 10:32:07 -05:00
Andrew Nicols d2979fb33f Merge branch 'MDL-61829-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-09 15:30:15 +08:00
Zig Tan ed3ab1da74 MDL-61829 block_community: Implement privacy provider 2018-04-09 14:12:12 +08:00
Mihail Geshoski 9f5aecebfe MDL-61867 fileconverter_unoconv: Add privacy files 2018-04-09 11:45:06 +08:00
Zig Tan 192e9b2e1e MDL-61881 report_usersessions: Implement null privacy provider 2018-04-09 10:48:37 +08:00
Zig Tan 737ab6eff8 MDL-61881 report_stats: Implement null privacy provider 2018-04-09 10:47:57 +08:00
Zig Tan 652ce0a4dd MDL-61881 report_security: Implement null privacy provider 2018-04-09 10:46:55 +08:00
Zig Tan 63de5af968 MDL-61881 report_questioninstances: Implement null privacy provider 2018-04-09 10:46:18 +08:00
Zig Tan 6bc3ca7a4c MDL-61881 report_performance: Implement null privacy provider 2018-04-09 10:41:15 +08:00
Helen Foster 5bb45aaa3c MDL-61033 mod_quiz: Update lang string 2018-04-09 10:41:04 +08:00
Andrew Nicols 34931397bc Merge branch 'MDL-61033-33' of https://github.com/nashtechdev01/moodle into MOODLE_33_STABLE 2018-04-09 10:40:56 +08:00
Zig Tan 747373c3f6 MDL-61881 report_participation: Implement null privacy provider 2018-04-09 10:40:20 +08:00
Zig Tan 31b0b02025 MDL-61881 report_outline: Implement null privacy provider 2018-04-09 10:39:22 +08:00
Zig Tan 168d335990 MDL-61881 report_loglive: Implement null privacy provider 2018-04-09 10:37:49 +08:00
Zig Tan 932689aa5e MDL-61881 report_log: Implement null privacy provider 2018-04-09 10:36:53 +08:00
Zig Tan 09913a019b MDL-61881 report_eventlist: Implement null privacy provider 2018-04-09 10:35:10 +08:00
Zig Tan dee60ecadb MDL-61881 report_courseoverview: Implement null privacy provider 2018-04-09 10:33:43 +08:00
Zig Tan 4017db1b69 MDL-61881 report_configlog: Implement null privacy provider 2018-04-09 10:32:27 +08:00
Zig Tan a2881f0511 MDL-61881 report_competency: Implement null privacy provider 2018-04-09 10:27:17 +08:00
Zig Tan da6c666441 MDL-61881 report_backup: Implement null privacy provider 2018-04-09 10:26:32 +08:00
Andrew Nicols 04de230de4 MDL-61896 filter: Implement privacy API for all filters 2018-04-08 15:54:34 +08:00
Andrew Nicols 89ed12aa50 MDL-61895 availability: Implement null provider for plugins 2018-04-08 14:23:23 +08:00
Andrew Nicols 767a4a4da5 MDL-61861 privacy: Add unit tests to check all providers. 2018-04-08 14:13:24 +08:00
Andrew Nicols 0014edcb6e MDL-61828 core_privacy: Support proper nesting in test trees 2018-04-08 13:31:31 +08:00
Charles Fulton 6a73402fdf MDL-61860 auth: standardise config inclusion 2018-04-07 12:20:30 -04:00
Willem Roes 67553b916f MDL-61708 mod_lti: use fullname for lis_person_name_full
Fullname passed on to LTI Provider was in format 'firstname lastname'
completely ignoring fullnamedisplay settings.
2018-04-07 09:33:14 +02:00
Luca Bösch dc57cba6be MDL-61581 lesson: style continue to last buttons 2018-04-06 16:41:46 +02:00
David Monllao 08cbe9b56c MDL-61621 blocks: New API function 2018-04-06 13:13:40 +02:00
cescobedo fd07089a41 MDL-61873 auth: Add privacy implementation for all auth plugins
None of the Auth plugins (except manual and oauth2) have any user preference or database table.
They all implement the null provider.
2018-04-06 13:13:27 +02:00
Andrew Nicols 77e236ca8f MDL-61861 core_tag: Correct langstring identifier 2018-04-06 14:21:59 +08:00
Mihail Geshoski f50f0978da MDL-61846 dataformat: Add privacy implementation for all plugins 2018-04-06 09:26:06 +08:00
Mihail Geshoski 30eced81da MDL-61843 report_completion: Add privacy files 2018-04-06 09:14:50 +08:00
Mihail Geshoski ea82e35775 MDL-61838 report_progress: Add privacy files 2018-04-06 09:01:26 +08:00
Eloy Lafuente (stronk7) 14fc7f597a weekly release 3.3.5+ 2018-04-05 15:38:08 +02:00
Eloy Lafuente (stronk7) 16c3e11c0d Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-04-05 15:38:06 +02:00
Jake Dallimore de3f8e2653 Merge branch 'MDL-61761-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-05 13:19:01 +08:00
Mihail Geshoski cc2454a92b MDL-61761 message_jabber: Add privacy files and unit tests 2018-04-05 11:59:38 +08:00
Jake Dallimore 01d52250a4 Merge branch 'wip-MDL-61163-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-04-05 10:37:46 +08:00
Andrew Nicols 2aa76eae1d Merge branch 'MDL-60726-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-04-05 08:39:39 +08:00
Eloy Lafuente (stronk7) 57d9e97c00 Merge branch 'MDL-61818-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-05 01:10:39 +02:00
Rohith e79517f1ee MDL-61746 PARAM_CLEANHTML: Fix documentation typos 2018-04-05 00:43:45 +02:00
Eloy Lafuente (stronk7) a000775fed Merge branch 'MDL-61781-33-fix' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-04-04 10:51:40 +02:00
Jun Pataleta 7bd0c3beba MDL-61781 admin_settings: Fix default settings value for docroot 2018-04-04 16:48:13 +08:00
Zig Tan 583281c7e6 MDL-60726 assign: Fix assign submission confirmation alignment 2018-04-04 16:35:30 +08:00
Andrew Nicols ed070b8d46 Merge branch 'MDL-61692-33-2' of https://github.com/snake/moodle into MOODLE_33_STABLE 2018-04-04 13:08:49 +08:00
Andrew Nicols 86b5c08a80 Merge branch 'wip-MDL-56635-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-04-04 11:32:42 +08:00
Jake Dallimore 6eb7886c9c MDL-61692 core_privacy: add privacyfields to link_ methods
Some subsystems are like conduits, passing data along to plugins which,
in turn, send the data externally. Only the component linking to (using)
the subsystem will know what data it is sending along to the eventual
external system, so should be able to specify this at the time of
linking. The same goes for plugintypes.
2018-04-04 10:04:07 +08:00
Andrew Nicols 80ca92cfc7 Merge branch 'MDL-61751-33-fix' of https://github.com/snake/moodle into MOODLE_33_STABLE 2018-04-04 09:12:08 +08:00
Jake Dallimore 958b46ad18 MDL-61751 core_plagiarism: fix fatal error with privacy legacy polyfill 2018-04-04 09:00:45 +08:00
Eloy Lafuente (stronk7) 742af6b337 Merge branch 'MDL-61451-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-04-04 01:40:57 +02:00
Eloy Lafuente (stronk7) 11e04e1bd4 Merge branch 'MDL-61817-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-04 01:23:22 +02:00
Eloy Lafuente (stronk7) 62a0907588 MDL-61751 core_plagiarism: add testsuite to phpunit.xml 2018-04-04 01:06:51 +02:00
Luca Bösch bbd4e0c745 MDL-61502 questions: add filter tests to gapselect question type. 2018-04-04 00:58:02 +02:00
Eloy Lafuente (stronk7) e3bcf576b1 Merge branch 'wip-MDL-61522-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-04-04 00:46:43 +02:00
Eloy Lafuente (stronk7) a98506c8e4 Merge branch 'MDL-61703-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-04 00:35:20 +02:00
Eloy Lafuente (stronk7) 4853023e80 Merge branch 'MDL-61751-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-04 00:24:08 +02:00
Eloy Lafuente (stronk7) 61ee905511 Merge branch 'MDL-61781-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-04-03 23:47:48 +02:00
Eloy Lafuente (stronk7) 04cfb8194a Merge branch 'MDL-61724-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-04-03 23:40:17 +02:00
Eloy Lafuente (stronk7) 623ee07cfe Merge branch 'MDL-60115-Book-cancel-button-redirect-bug-33' of https://github.com/Moodlers/moodle-1 into MOODLE_33_STABLE 2018-04-03 21:46:41 +02:00
Marcus Fabriczy a83ceb2be8 MDL-60196 core_course: Fix the display of custom LTI icons
Custom LTI icons attached to LTI tools did not display - a regression
caused by MDL-55796.

Change-Id: I9b956f4b4959a992fe763cdb05cf684cd92cc8de
2018-04-03 20:37:45 +09:30
Jake Dallimore 1b6f7526df Merge branch 'wip-MDL-61815-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-03 17:54:43 +08:00
Jake Dallimore 707e1c5527 Merge branch 'wip-MDL-61127-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-03 17:35:58 +08:00
Adrian Greeve cbca0b7c89 MDL-61127 filepicker: Selected repository now highlighted. 2018-04-03 16:44:38 +08:00
Adrian Greeve b2ee1cf532 MDL-61127 filepicker: Added aria-selected attribute to repos.
The repository list in the file picker now as aria-selected
added to denote which repository is selected.
2018-04-03 16:44:30 +08:00
Andrew Nicols 5e8a151aff Merge branch 'wip-MDL-61629-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-04-03 16:00:25 +08:00
Adrian Greeve fcedf5a69b MDL-61629 message_airnotifier: Add privacy files and unit tests. 2018-04-03 14:47:19 +08:00
Andrew Nicols abf6c76dbf Merge branch 'MDL-61020-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-04-03 14:21:58 +08:00
Adrian Greeve 1b842c1eed MDL-61815 core_privacy: Fix for metadata types and new method.
Minor fix for subsystem_link and plugintype_link.
Addition of get_null_provider_reason in the manager class.
2018-04-03 13:57:33 +08:00
Eloy Lafuente (stronk7) 036ab38556 Merge branch 'MDL-61689-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-03 01:17:35 +02:00
Eloy Lafuente (stronk7) 2baf76b657 MDL-61223 course: keep some tests using old values (January 1st 1970) 2018-04-03 00:14:01 +02:00
Andrew Nicols 01ac2dfe67 MDL-61223 course: Set default course start date 2018-04-02 12:04:21 +02:00
Eloy Lafuente (stronk7) 8dd32ca48b Merge branch 'MDL-61801-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-04-02 11:04:28 +02:00
Andrew Nicols 1b0e5bbcd3 MDL-61817 tinymce: Add privacy implementation for all plugins
None of the TinyMCE plugins have any user preference or database table.
They all implement the null provider.
2018-04-02 13:51:20 +08:00
Andrew Nicols c1034f8595 MDL-61818 antivirus: Implement core_privacy API 2018-04-02 13:46:42 +08:00
Michael Brown 06a28cd3e7 MDL-60115 mod_book: Book Resource Cancel Button Redirect Bug
When the user creates a book but adds no chapters, hitting cancel on
 the chapter creation page would redirect you right back to the same
 page with no explanation. This solution redirects to the course page
 when canceling chapter creation when no chapters are present.
2018-04-02 04:12:59 +00:00
Andrew Nicols c7640874bf MDL-61751 core_privacy: Correct test return 2018-04-01 13:36:57 +08:00
Jake Dallimore 458c700143 MDL-61751 core_plagiarism: add polyfill for plagiarism provider 2018-04-01 13:36:57 +08:00
AMOS bot 6a4148c734 Automatically generated installer lang files 2018-03-31 00:07:25 +00:00
Andrew Nicols e9dbec72f8 MDL-61801 core_privacy: Correct bug in unit test provider 2018-03-29 22:45:43 +08:00
Luca Bösch b555c2aee0 MDL-61781 installation: docs link should have https. 2018-03-29 12:12:39 +02:00
Andrew Nicols 147174ffbb MDL-61703 privacy: Allow writing of user preferences at any context 2018-03-29 15:29:45 +08:00
Jun Pataleta 6a643e96d6 weekly release 3.3.5+ 2018-03-29 12:55:55 +08:00
Jun Pataleta 0742adc1f8 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-03-29 12:55:54 +08:00
Marina Glancy 33e486cad6 MDL-61163 mod_wiki: guests should be able to view frontpage modules
When wiki is added to the frontpage and the guest role has capability to view
wiki, users should not be required to log in.
2018-03-29 11:12:41 +08:00
Marina Glancy 2c89620ad0 MDL-61163 mod_wiki: add default view capability to frontpage
It is inconsistent that guests are allowed to view frontpage wiki but once user is logged in they
loose this capability
2018-03-29 11:12:41 +08:00
Marina Glancy 96e983e488 MDL-61163 mod_wiki: correct capability check in modinfo
Wiki defines capability mod/wiki:viewpage instead of standard mod/wiki:view . This means that people
who do not have capability to view wiki still see it in the modules list.

Also corrected unittest that was testing situation when student has capability to create pages
but does not have capability to view pages. Such student should not see wiki module at all.
2018-03-29 11:12:40 +08:00
Jake Dallimore c2abd2c0f0 Merge branch 'MDL-61770-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-28 13:35:55 +08:00
Andrew Nicols 8256acd42e MDL-61770 iplookup: Check types rather than values 2018-03-28 10:58:49 +08:00
Shamim Rezaie 4b057b9d1a MDL-61020 media_videojs: Fix RTL display issues 2018-03-28 13:38:14 +11:00
Eloy Lafuente (stronk7) 085f325851 Merge branch 'MDL-39060-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-03-27 13:45:53 +02:00
Ankit Agarwal 4d26291ddc MDL-51362 libraries: Remove deprecated admin tool unittest 2018-03-27 13:39:38 +02:00
Eloy Lafuente (stronk7) 6dcb3a1692 Merge branch 'MDL-61321-33' of git://github.com/jleyva/moodle into MOODLE_33_STABLE 2018-03-27 12:45:20 +02:00
Jun Pataleta b2970055de Merge branch 'MDL-60762-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-03-27 15:47:07 +08:00
Adam Pawełczak 0ac58fc0d7 MDL-60762 tool_usertours: Respect $CFG->admin in manager.php 2018-03-27 15:23:07 +08:00
Jun Pataleta 558fc27a1d Merge branch 'wip-MDL-61328-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-03-27 13:50:01 +08:00
Jun Pataleta 7c6310c1c0 Merge branch 'MDL-61257-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-03-27 12:52:56 +08:00
dinhloc 5d70a00dd8 MDL-61033 quiz: Editing a quiz while a preview is open
Editing a quiz while a preview is open in another browser tab can leads to a cryptic error that is hard to recover from
2018-03-27 11:32:44 +07:00
Jun Pataleta e78265a235 Merge branch 'MDL-61656_33' of git://github.com/stronk7/moodle into MOODLE_33_STABLE 2018-03-27 12:11:22 +08:00
Eloy Lafuente (stronk7) 99c4c947fe Merge branch 'MDL-61248_m33' of https://github.com/ak4t0sh/moodle into MOODLE_33_STABLE 2018-03-27 01:43:11 +02:00
Eloy Lafuente (stronk7) 57f1a4adc7 Merge branch 'MDL-61576-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-03-26 23:26:30 +02:00
Eloy Lafuente (stronk7) 7c08cacca7 Merge branch 'MDL-61691-33' of https://github.com/snake/moodle into MOODLE_33_STABLE 2018-03-26 23:15:28 +02:00
Andrew Nicols 69b780e97a Merge branch 'MDL-55532-33' of git://github.com/lameze/moodle into MOODLE_33_STABLE 2018-03-26 15:36:27 +08:00
Andrew Nicols 9f271d765d Merge branch 'MDL-61733-33' of https://github.com/MartinGauk/moodle into MOODLE_33_STABLE 2018-03-26 15:02:41 +08:00
Jake Dallimore 8f8d4649b6 MDL-61691 core_plagiarism: fix namespace in privacy provider interface 2018-03-26 12:30:45 +08:00
Mihail Geshoski 543afc2850 MDL-61257 reports: Report logs link to unavailable completion report 2018-03-26 12:25:29 +08:00
Nick Phillips be17ced747 MDL-55532 gradebook: fix grade export to include category names 2018-03-26 11:50:13 +08:00
Mihail Geshoski 783eecec41 MDL-61724 resource: Unable to view or download file resource 2018-03-26 11:21:40 +08:00
Marina Glancy 71092f49c9 MDL-61328 tool_usertours: do not fix tour sortorder after step editing
otherwise it breaks when we try to modify the step sortorder
2018-03-26 09:52:59 +08:00
Zig Tan 1892dd565f MDL-39060 backup: fix typo backup destroy() function 2018-03-26 09:28:59 +08:00
AMOS bot a269833f80 Automatically generated installer lang files 2018-03-25 00:06:35 +00:00
David Mudrák 49f57eb19d MDL-61741 enrol_paypal: Prevent some edge-case false errors
While testing the plugin in various scenarios, I've noticed that there
are two situations which the current code does not handle quite well:

* Detecting for existing txn_id record was likely to throw "found more
  than one record" debugging message. Fixed by explicitly ignoring
  multiple records.
* The incoming IPN verification message does not always contain the
  recipient's email in the "business" field. When a payment has to be
  claimed manually at PayPal (e.g. as a result of currencies mismatch
  and other settings), the email is coming only in the "receiver_email"
  field. This led to PHP notice and caused the script to fail falsely.
2018-03-23 19:51:43 +01:00
David Mudrák 6f420dc5d0 MDL-61741 enrol_paypal: Fix the IPN verification endpoint URL
IPN protocol spec has different URL for sending the verification
request. Better to have it fixed even if the existing value still
seems to work - to avoid unexpected surprise in the future.

Source: https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNImplementation/#specs
2018-03-23 19:45:27 +01:00
Arnaud Trouvé a27e44f244 MDL-61248 admin: fix incorrectly initialized property 2018-03-23 16:23:21 +01:00
Martin Gauk 577410806c MDL-61733 atto_table: fix creating new table
If Atto is embedded in an HTML table (e.g. in the database activity
on the template pages), you could not create a new table.
2018-03-23 09:48:05 +00:00
Eloy Lafuente (stronk7) c6846832d5 weekly release 3.3.5+ 2018-03-22 16:57:11 +01:00
Eloy Lafuente (stronk7) 5bfbe050ee Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-03-22 16:57:09 +01:00
Jake Dallimore 9237d70fc8 Merge branch 'MDL-58179-33-fix' of https://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-22 12:06:50 +08:00
Andrew Nicols ff565b1f9c MDL-58179 mod_lesson: Add missing : in labels 2018-03-22 12:02:21 +08:00
Andrew Nicols f9bd55fae3 Merge branch 'MDL-61530-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-22 11:49:55 +08:00
Renaat Debleu a6b5e1366e MDL-61530 mod_glossary: import_entries.feature needs @_file_upload tag 2018-03-22 11:45:28 +08:00
Jun Pataleta f4733abf2a Merge branch 'MDL-52989-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-03-22 11:29:34 +08:00
Jun Pataleta 862439c883 MDL-52989 mod_lesson: Fix typo in feature description 2018-03-22 11:28:53 +08:00
Luca Bösch e9786dc883 MDL-52989 mod_lesson: Fix cluster_jump returning a cluster page id. 2018-03-22 11:28:52 +08:00
Eloy Lafuente (stronk7) 7c9b564f3f Merge branch 'MDL-61658-33-allcountrycodes' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-03-21 19:38:13 +01:00
David Mudrák 041072f63c MDL-61658 user: Fix displaying of user's country name
In these cases we want to use the method get_list_of_countries() to
obtain translated names of all potential country codes. The country code
is already there in the database. So it does not matter if the country
is among those whitelisted in $CFG->allcountrycodes - we want to see its
name anyway.
2018-03-21 18:07:13 +01:00
David Mudrák bc4e9f628c MDL-61658 user: Fix parsing of the agedigitalconsentmap setting
When parsing and validating the value of the Digital age of consent
(agedigitalconsentmap) field, we want to load all country codes. Not
just the ones whitelisted for drop down menus that users can choose
from.
2018-03-21 18:07:13 +01:00
AMOS bot 85b56ae4f7 Automatically generated installer lang files 2018-03-21 00:06:23 +00:00
Juan Leyva 48dfcbe27b MDL-61321 mod_feedback: Return all the items responses
The WS should receive all the item responses for all the attempts.
2018-03-20 10:37:41 +01:00
Luca Bösch 2f0b720d6c MDL-58179 lesson: Avoid using span with class "label" 2018-03-20 13:48:41 +08:00
Andrew Nicols 26a4ad65dc MDL-61597 calendartype: Implement the privacy API 2018-03-20 02:27:32 +01:00
Andrew Nicols 8269544f2f MDL-61689 phpunit: Be stricter about output during unit tests
This change also add fail-on-risky to travis to help pick these up, and
verbosity too.

We only fail on risky during Travis and not during normal output because
developers may want to debug tests.
2018-03-20 08:33:13 +08:00
AMOS bot 775b6d0d50 Automatically generated installer lang files 2018-03-20 00:06:22 +00:00
AMOS bot 25627e446f Automatically generated installer lang files 2018-03-20 00:06:22 +00:00
Andrew Nicols eb82d420f0 Merge branch 'MDL-61265-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-03-19 10:52:10 +08:00
Andrew Nicols bc360e9441 Merge branch 'MDL-58179-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-03-19 10:32:29 +08:00
Eloy Lafuente (stronk7) e786a591d5 Moodle release 3.3.5 2018-03-17 01:18:30 +01:00
Eloy Lafuente (stronk7) d9321f3342 Merge branch 'MDL-61672-33-abstractstaticmethod' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-03-16 23:26:10 +01:00
David Mudrák b2865ca1e4 MDL-61672 admin: Fix sitepolicy handler API
The base class had abstract static methods which raises strict standards
warning on PHP 5.6.
2018-03-16 17:22:45 +01:00
cescobedo c1ae0d9bc4 MDL-61451 message_area: core/auto_rows remove set height to 1px 2018-03-16 13:02:24 +01:00
Sara Arjona 7dc3c9b24e MDL-61265 enrol: Add default numsections for external db 2018-03-16 11:33:33 +01:00
cescobedo 170abe6a2b MDL-61576 mod_lti: remove allowinstructorcustom in lib/locallib.php 2018-03-16 10:41:35 +01:00
Luca Bösch a1e64b07b5 MDL-58179 lesson: Avoid using span with class "label" 2018-03-16 08:47:18 +01:00
Jake Dallimore 9973df93f4 weekly release 3.3.4+ 2018-03-16 10:08:50 +08:00
Eloy Lafuente (stronk7) a68417183c MDL-61656 report_security: fix role name 2018-03-16 02:26:24 +01:00
Eloy Lafuente (stronk7) 9e21adb5f7 Merge branch 'MDL-61570-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-16 01:15:35 +01:00
Andrew Nicols 65c23f097c MDL-61570 tool_usertours: Implement Privacy API 2018-03-16 08:13:04 +08:00
Eloy Lafuente (stronk7) 92be49df49 MDL-61566 theme: PHP 5.6 compatibility 2018-03-16 00:48:58 +01:00
Eloy Lafuente (stronk7) 7eab2af613 Merge branch 'MDL-61566-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-16 00:30:08 +01:00
Eloy Lafuente (stronk7) 5fb193152e Merge branch 'MDL-61571-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-15 23:51:09 +01:00
Jake Dallimore 44080d810b Merge branch 'wip-MDL-61477-33-behat' of https://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-03-15 16:44:57 +08:00
Marina Glancy c525fe3095 MDL-61477 auth_email: behat tests for sign up 2018-03-15 16:22:13 +08:00
Jake Dallimore 86fe3ca41b Merge branch 'wip-MDL-61477-33-manager' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-03-15 11:41:12 +08:00
Marina Glancy 20884e18e5 MDL-61477 admin: sitepolicy handler API
- Define sitepolicy handler manager class, base class and the core handler
- Allow to set a plugin as sitepolicyhandler that implements the sitepolicy API
- Modify web services to return information from the 3rd party handler instead of core if needed
2018-03-15 11:31:30 +08:00
David Mudrák b0b49c938b MDL-61477 admin: Allow plugins to act as alternate policy handlers
The patch introduces a new site setting 'sitepolicyhandler' that can be
either empty or contain a plugin component name. If it is empty, the
site policy feature keeps working as before and the core keeps the
control over it.

If a plugin is specified, it is expected to implement the callback
'site_policy_handler' in its lib.php file. The callback should return a
URL to a script where the user can accept the site policies. The plugin
itself is responsible for setting the 'policyagreed' flag in the users
table. The callback may return an empty value, in which case the user
can continue using the site without being redirected.

The patch adds support for a new pre-config flag NO_SITEPOLICY_CHECK.
This constant should be defined and set to true if we should not check
the user's policyagreed status during the require_login().

This is for pages where the user actually accepts the site policies and
helps to avoid the redirect loop.
2018-03-15 09:30:05 +08:00
Eloy Lafuente (stronk7) 2e6acd5f60 Merge branch 'MDL-61600-33' of git://github.com/dpalou/moodle into MOODLE_33_STABLE 2018-03-14 14:43:47 +01:00
Eloy Lafuente (stronk7) b0e4353ddd Merge branch 'MDL-61620_33' of git://github.com/dmonllao/moodle into MOODLE_33_STABLE 2018-03-14 13:38:59 +01:00
David Monllao 16edec0104 MDL-61620 output: New action_menu options 2018-03-14 11:38:32 +01:00
Eloy Lafuente (stronk7) 07c9c193b3 Merge branch 'MDL-61398-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-14 11:22:33 +01:00
Eloy Lafuente (stronk7) 0817548194 Merge branch 'MDL-61475-33-v3' of git://github.com/snake/moodle into MOODLE_33_STABLE 2018-03-14 11:01:18 +01:00
Dani Palou 3585740ced MDL-61600 recaptcha: Create a script to display recaptcha 2018-03-14 10:35:35 +01:00
Andrew Nicols 1cf00cde92 Merge branch 'MDL-60398-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-03-14 10:34:09 +08:00
Jake Dallimore 4ee7ad2377 Merge branch 'MDL-61307-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-14 09:46:06 +08:00
Jake Dallimore 9cdf3e4316 MDL-61475 mod_choice: perf improvement when exporting personal data
Instead of creating an array containing all record information and then
writing, we know write periodically during the recordset iteration, thus
alleviating any memory concerns associated with the array approach.
2018-03-14 09:37:57 +08:00
Jake Dallimore 60bf7bf6c2 MDL-61475 mod_choice: Update core_privacy implementation 2018-03-14 09:37:57 +08:00
Jun Pataleta d378b3a50e MDL-61475 mod_choice: Add implementation of Privacy API 2018-03-14 09:37:57 +08:00
Andrew Nicols 82c9aa61a8 MDL-61398 block_html: Implement privacy API 2018-03-14 09:33:16 +08:00
Andrew Nicols cb8197f594 MDL-61307 core_privacy: Add unit test to check installed providers 2018-03-14 09:32:32 +08:00
David Mudrák 9873a175a5 MDL-61392 enrol_paypal: Improve IPN input parameters checking 2018-03-14 09:12:09 +08:00
David Mudrák 89033d2d07 MDL-61392 enrol_paypal: Improve the IPN notifications handling
* Notify administrators once incoming IPN request is verified by PayPal.
* Fix the HTTP status as expected by the IPN protocol.
2018-03-14 09:12:09 +08:00
Eloy Lafuente (stronk7) 110e818da7 Merge branch 'MDL-61625_33' of git://github.com/dmonllao/moodle into MOODLE_33_STABLE 2018-03-14 00:59:29 +01:00
David Mudrák 5d06da4e41 MDL-60101 auth_oauth2: Don't allow suspended users to SSO in via OAuth2
Without this patch, users could still log in as a suspended account via
OAuth2 SSO feature.
2018-03-13 10:13:00 +01:00
Jake Dallimore 78ebc5d9e7 Merge branch 'm33_MDL-61626_PgSQL_Table_Name_Could_Be_Schema_Qualified' of https://github.com/scara/moodle into MOODLE_33_STABLE 2018-03-13 15:38:15 +08:00
Andrew Nicols d8952802e7 Merge branch 'MDL-59070-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-03-13 13:55:25 +08:00
Andrew Nicols 7a49ac3d79 Merge branch 'MDL-61397-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-03-13 12:59:47 +08:00
Andrew Nicols 1983c83957 Merge branch 'MDL-61567-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-03-13 12:21:36 +08:00
Eloy Lafuente (stronk7) 1b1b6313c0 Merge branch 'MDL-61307-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-13 03:27:53 +01:00
Zig Tan d2bc47577b MDL-61397 blocks: Fix null_provider namespace for blocks
Also added null provider for block_messages
2018-03-13 10:07:44 +08:00
Andrew Nicols 674a9c859d MDL-61307 core: Language changes 2018-03-13 09:42:23 +08:00
Andrew Nicols 56335cc001 MDL-61307 privacy: Rename deletion functions 2018-03-13 08:52:26 +08:00
Andrew Nicols 2e86cca9ca MDL-61307 core: Remove deletion_criteria 2018-03-13 08:50:27 +08:00
Eloy Lafuente (stronk7) 0913f3314f Merge branch 'MDL-48501-mdl33' of git://github.com/jswebster/moodle into MOODLE_33_STABLE 2018-03-12 23:51:06 +01:00
Matteo Scaramuccia cf7979c622 MDL-61626 core_dml: pgsql and schema qualification. 2018-03-12 22:52:37 +01:00
Eloy Lafuente (stronk7) cda6d082de Merge branch 'wip-MDL-60241-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-03-12 18:29:00 +01:00
Eloy Lafuente (stronk7) eb12fec156 Merge branch 'MDL-61397-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-12 17:31:35 +01:00
Eloy Lafuente (stronk7) d2c04300f3 Merge branch 'MDL-61622-33' of git://github.com/jleyva/moodle into MOODLE_33_STABLE 2018-03-12 11:37:16 +01:00
David Monllao ceb21de5e3 MDL-61625 persistent form: Add missing param to the constructor 2018-03-12 08:10:40 +01:00
Andrew Nicols 6aef716ec4 MDL-61566 theme: Add Privacy providers for all core themes 2018-03-12 13:28:08 +08:00
Andrew Nicols fc16e61230 MDL-61571 atto: Implement null provider for atto plugins 2018-03-12 13:22:58 +08:00
Andrew Nicols 0534fbc2aa Merge branch 'MDL-61513-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-03-12 12:26:48 +08:00
Andrew Nicols 5b9f872429 Merge branch 'MDL-61498-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-03-12 12:08:07 +08:00
Andrew Nicols dd67898152 Merge branch 'MDL-61261-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-03-12 11:52:31 +08:00
Zig Tan 2377dbd9d8 MDL-61567 mod_url: Implement null provider mod_url 2018-03-12 11:24:21 +08:00
Zig Tan 3810c3ad36 MDL-61567 mod_resource: Implement null provider mod_resource 2018-03-12 11:23:56 +08:00
Zig Tan ef9c44ad7e MDL-61567 mod_page: Implement null provider mod_page 2018-03-12 11:23:26 +08:00
Zig Tan 3eac779614 MDL-61567 mod_label: Implement null provider mod_label 2018-03-12 11:20:33 +08:00
Zig Tan 5223ceed6b MDL-61567 mod_folder: Implement null provider mod_folder 2018-03-12 11:19:57 +08:00
Zig Tan f27cf98517 MDL-61397 blocks: Add null_providers for blocks with no user data 2018-03-12 08:46:33 +08:00
Juan Leyva 7fe0a3b051 MDL-61622 auth: New WS is_age_digital_consent_verification_enabled 2018-03-09 18:13:59 +01:00
Jake Dallimore f03765aae7 Merge branch 'MDL-61307-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-03-09 13:37:40 +08:00
Andrew Nicols 9fa3922c77 MDL-61307 core_plagiarism: Add implementation of Privacy API 2018-03-09 12:24:39 +08:00
Andrew Nicols 4a9c1685bd MDL-61307 core_privacy: Add legacy polyfill for contrib plugins
This legacy polyfill allows plugin developers who release a single
branch to work with multiple versions of Moodle to support the API in
both Moodle 3.3 with PHP 5.6, and later versions.
2018-03-09 12:24:39 +08:00
Andrew Nicols fbb3918ebe MDL-61307 core_privacy: Implementation of itself 2018-03-09 12:24:39 +08:00
Adrian Greeve d17dc20947 MDL-61307 core_comment: Add implementation of privacy API 2018-03-09 12:24:39 +08:00
Andrew Nicols a63717d365 MDL-61307 core_rating: Add implementation of Privacy API 2018-03-09 12:24:38 +08:00
Zig Tan 0867abed26 MDL-61307 core_tag: Unit tests for privacy implementation 2018-03-09 12:24:38 +08:00
Andrew Nicols be94915636 MDL-61307 core_tag: Add implementation of privacy API 2018-03-09 12:24:38 +08:00
Jake Dallimore 5de4b14160 MDL-61307 core_privacy: Add the privacy manager 2018-03-09 12:24:38 +08:00
Marina Glancy 3e316b8713 MDL-60241 course: General section always visible (topics, weeks) 2018-03-09 12:11:31 +08:00
Andrew Nicols 267e1af112 MDL-61307 core_privacy: Define and test providers 2018-03-09 10:03:29 +08:00
Andrew Nicols 37db3b8561 MDL-61307 core: Add component_class_callback functionality 2018-03-09 10:03:29 +08:00
Andrew Nicols 5a146aa633 MDL-61307 core: Define a new privacy component 2018-03-09 10:03:28 +08:00
Jeff Webster 934220228a MDL-48501 auth/email: update external class to use reCAPTCHA v2 2018-03-08 14:22:39 -05:00
Jeff Webster 3c9a5ae1cc MDL-48501 mod_feedback: update feedback to use reCAPTCHA v2 2018-03-08 14:22:39 -05:00
Jeff Webster 8d7d722fb0 MDL-48501 login: update signup_form to use reCAPTCHA v2 2018-03-08 14:22:39 -05:00
Jeff Webster 2f0be313b3 MDL-48501 form/recaptcha: update to use reCAPTCHA v2 2018-03-08 14:22:39 -05:00
Jeff Webster 68e6299010 MDL-48501 recaptchalib_v2: add new lib to support reCAPTCHA v2 2018-03-08 14:22:39 -05:00
Jeff Webster e3a18e4458 MDL-48501 lang: update reCAPTCHA language strings 2018-03-08 14:22:39 -05:00
Luca Bösch 21d27e3f96 MDL-59070 enrol_database: Take enablecompletion from template 2018-03-08 17:22:52 +01:00
Luca Bösch a74a3f8ab8 MDL-61498 lesson: link to next activity in boost 2018-03-08 17:22:26 +01:00
Eloy Lafuente (stronk7) e95f91c90a weekly release 3.3.4+ 2018-03-08 13:29:10 +01:00
Eloy Lafuente (stronk7) 7a793db488 NOBUG: Fixed SVG browser compatibility 2018-03-08 13:29:09 +01:00
Eloy Lafuente (stronk7) 645b80ea72 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-03-08 13:29:08 +01:00
Andrew Nicols 5c07c79657 Merge branch 'MDL-61423-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-03-08 15:30:36 +08:00
Mihail Geshoski 5cb155ad9d MDL-61423 authentication: Add digital minor verification upon signup 2018-03-08 15:03:05 +08:00
Eloy Lafuente (stronk7) a8b5704fb4 Merge branch 'MDL-60445-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-03-07 19:20:21 +01:00
Jesse Ritchey 707d3a3aa3 MDL-60445 theme_boost: remove fieldset tag 2018-03-07 11:09:04 +01:00
Andrew Nicols 9f11f13ad8 Merge branch 'WIP-MDL-60658-33' of https://github.com/chkhanu/moodle into MOODLE_33_STABLE 2018-03-07 11:37:45 +08:00
Andrew Nicols b091c290bb Merge branch 'wip-MDL-61322-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-03-07 10:58:24 +08:00
Andrew Nicols c101a623d8 Merge branch 'MDL-61497-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-03-07 10:28:49 +08:00
AMOS bot 5815d6f01c Automatically generated installer lang files 2018-03-07 00:06:38 +00:00
Eloy Lafuente (stronk7) 2e17137c8b Merge branch 'MDL-36157-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-03-06 02:52:41 +01:00
Luca Bösch 28b6ae97e9 MDL-36157 block_rss_client: Don't double escape titles. 2018-03-06 00:20:33 +01:00
Luca Bösch d527a497ea MDL-36157 block_rss_client: Don't double escape titles. 2018-03-06 00:20:32 +01:00
Eloy Lafuente (stronk7) 64488fd069 Merge branch 'MDL-61211-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-03-05 23:33:44 +01:00
Eloy Lafuente (stronk7) 76148061d7 Merge branch 'MDL-55153-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-03-05 23:26:12 +01:00
Andrew Nicols 9214166d89 MDL-61268 core: Fix empty string DB cehck
(amended by stronk7 to use the helper better)
2018-03-02 16:32:36 +01:00
Andrew Nicols 253fcd9ce2 Merge branch 'wip-MDL-61268-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-03-02 10:03:58 +08:00
Adrian Greeve 218cbbed31 MDL-61268 blocks: Unit tests for deprecated object update.
Unit tests for testing that the upgrade functions to change
the now deprecated object to stdClass works.
2018-03-02 09:39:16 +08:00
Adrian Greeve b3dfb6eafa MDL-61268 blocks: Fix corrupt configdata in block instances.
Old configuration data in the block instances is base64 encoded with
the deprecated object class instead of stdClass.
2018-03-02 09:38:59 +08:00
Andrew Nicols 8fda9b0267 Merge branch 'MDL-61196_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-03-02 09:35:03 +08:00
Eloy Lafuente (stronk7) 5fafbd8a3c Merge branch 'MDL-61533-33-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-03-02 01:43:12 +01:00
Helen Foster 9a550cac49 MDL-61533 lang: Merge English strings from the en_fix language pack
Significant string change:

* typeoflogin_desc,tool_mobile - removing sentence about autologinguests
2018-03-01 15:35:05 +01:00
Luca Bösch ffd593db80 MDL-61497 repository_onedrive: Use post 2015 icon 2018-03-01 08:57:29 +01:00
Chernyavskiy Leonid 14618260c8 MDL-60658 course, gradebook: fix missing unformat_float for gradepass
Fix incorrect comparison of gradepass variable (with comma as decimal separator)
with grade variable when trying to save assignment settings.
Adds missing unformat_float($data['gradepass']).
2018-03-01 09:27:08 +07:00
Mihail Geshoski 7f1fcbda75 MDL-61211 lesson: Error when answer or response contains break tag 2018-03-01 09:52:22 +08:00
Andrew Nicols 5fc058c0b0 Merge branch 'MDL-61453-33-userpicturefiletype' of git://github.com/mudrd8mz/moodle into MOODLE_33_STABLE 2018-03-01 08:46:44 +08:00
Eloy Lafuente (stronk7) 2faddcdef5 weekly release 3.3.4+ 2018-02-28 12:58:18 +01:00
Jake Dallimore a49458943c Merge branch 'wip-MDL-61485-33' of git://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-02-27 09:40:40 +08:00
Jake Dallimore aaf815541b Merge branch 'MDL-61480-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-02-27 09:05:42 +08:00
David Mudrák eb618c1c71 MDL-61453 user: Fix accepted file type when uploading user pictures
Not all archives are supported, only ZIP files are.
2018-02-26 14:32:55 +01:00
Mihail Geshoski 4948a43536 MDL-60398 resource: Unable to download folder resource 2018-02-26 16:54:23 +08:00
Andrew Nicols b4a4b7ce70 Merge branch 'wip-MDL-61455-33' of https://github.com/marinaglancy/moodle into MOODLE_33_STABLE 2018-02-26 14:12:04 +08:00
Andrew Nicols 4f21e3a33f MDL-61480 core: Check plugin installed before returning 2018-02-26 12:12:08 +08:00
Andrew Nicols d6e63cb602 Merge branch 'MDL-60547-33' of git://github.com/cescobedo/moodle into MOODLE_33_STABLE 2018-02-26 10:27:56 +08:00
Andrew Nicols 504e36da8e Merge branch 'MDL-61462-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-26 10:19:00 +08:00
Jake Dallimore 9c796e028d weekly release 3.3.4+ 2018-02-23 11:51:32 +08:00
Jake Dallimore 3a7f56c779 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-02-23 11:51:31 +08:00
Marina Glancy c982d78c20 MDL-61522 mod_glossary: use full url in links 2018-02-23 10:56:22 +08:00
Carlos c4f22db315 MDL-60547 message_popup: adding preventDefault at notification popover 2018-02-22 10:53:51 +01:00
Jun Pataleta f926f376f8 MDL-61513 admin: Fix undefined $buttons variable 2018-02-22 10:22:38 +08:00
Eloy Lafuente (stronk7) 6972f8403f Merge branch 'MDL-61324_lti_sync_33' of git://github.com/davosmith/moodle into MOODLE_33_STABLE 2018-02-22 08:31:59 +08:00
Dan Marsden 457fcfe3d0 MDL-61005 core_cohort: Allow teachers to view site-wide cohorts 2018-02-22 08:31:59 +08:00
Luca Bösch bf085b7fc5 MDL-58845 mod_choice: Fix behat related tests 2018-02-22 08:31:58 +08:00
Andrew Nicols 2eb83b7678 Merge branch 'MDL-61421-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-02-22 08:31:57 +08:00
Andrew Nicols a3e647dc98 Merge branch 'MDL-61408-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-02-22 08:31:57 +08:00
Sara Arjona a5bac67326 MDL-55153 customlang: Remove local DB entries when deleting local file 2018-02-21 21:04:57 +01:00
Damyon Wiese 3117287072 MDL-61455 autocomplete: Return promise
Partial backport of MDL-59368
2018-02-21 09:40:07 +08:00
Mihail Geshoski f6121c0bd6 MDL-61485 authentication: Add callback 'pre_signup_requests' 2018-02-20 10:00:02 +08:00
Eloy Lafuente (stronk7) fd1ef60779 Merge branch 'MDL-58845-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-02-19 02:13:07 +01:00
Andrew Nicols ff1f239381 Merge branch 'MDL-61289-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-19 09:08:00 +08:00
Jun Pataleta 6c855610bf MDL-61289 mod_choice: Add extra user fields to response data 2018-02-19 08:54:39 +08:00
AMOS bot 8b1eb7742e Automatically generated installer lang files 2018-02-19 00:06:34 +00:00
AMOS bot 08e1bbd86b Automatically generated installer lang files 2018-02-17 00:06:37 +00:00
Luca Bösch b899bab0bc MDL-61408 qbehaviour: Correct "Check" button styling. 2018-02-16 08:43:45 +01:00
Luca Bösch 48352701a1 MDL-58845 mod_choice: In reports, respect "Show column for unanswered" 2018-02-16 08:43:42 +01:00
Jun Pataleta f23541f3fb MDL-61462 admin_roles: Point back to roles link to the correct URL 2018-02-16 10:33:25 +08:00
Damyon Wiese ab83a52583 MDL-61455 boost: Don't allow z-index on pagination MDL-59809
This causes parts of the pagination bar to show through overlays and modals.
2018-02-16 10:08:12 +08:00
Marina Glancy 7f3c09ae49 MDL-56635 tags: use recordset since component may not be unique 2018-02-16 09:51:21 +08:00
Eloy Lafuente (stronk7) 2e8f163f64 weekly release 3.3.4+ 2018-02-15 17:10:27 +01:00
Andrew Nicols 41275ea779 Merge branch 'wip-33-MDL-61344' of https://github.com/ndunand/moodle into MOODLE_33_STABLE 2018-02-13 09:04:45 +08:00
Andrew Nicols e129c4733b Merge branch 'MDL-61150_33' of git://github.com/stronk7/moodle into MOODLE_33_STABLE 2018-02-13 09:02:53 +08:00
David Monllao 8904b10b44 Merge branch 'MDL-61236-33' of git://github.com/farhan6318/moodle into MOODLE_33_STABLE 2018-02-12 12:14:28 +01:00
Nicolas Dunand 5e092e2540 MDL-61344 mod_assign: Show additional files when adding submission 2018-02-12 11:13:55 +01:00
David Monllao 235d4be426 Merge branch 'MDL-61153-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-02-12 10:56:14 +01:00
David Monllao 0ce2cf80ee Merge branch 'MDL-61375_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-02-12 09:41:04 +01:00
Nick Phillips 7d5efd643c MDL-56688 grade: fix ordering of grade items in grade_seq::flatten 2018-02-12 09:35:16 +01:00
Davo Smith 8566cace36 MDL-61324 enrol_lti: fix detection of changed grades during sync 2018-02-12 08:26:59 +00:00
David Monllao f71d4d4a97 Merge branch 'mod-lti-fix-test-with-hardcoded-url-mdl33' of https://github.com/peikk0/moodle into MOODLE_33_STABLE 2018-02-12 09:21:04 +01:00
David Monllao ccd495d806 Merge branch 'MDL-61425-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-02-12 09:13:20 +01:00
Sara Arjona 5613a37ab2 MDL-61421 cohort: Fix cohort_role_sync when a user is in two cohorts 2018-02-12 09:10:14 +01:00
Andrew Nicols 8e2eb1f335 Merge branch 'MDL-61366_33' of git://github.com/timhunt/moodle into MOODLE_33_STABLE 2018-02-12 15:26:39 +08:00
Shamim Rezaie 89660817f7 MDL-61425 theme_boost: Made question labels width full in question bank 2018-02-12 14:54:32 +11:00
Andrew Nicols ea61136232 Merge branch 'MDL-61305-33-fix' of https://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-02-12 11:32:10 +08:00
Andrew Nicols 9a36044425 MDL-61305 modinfo: Add back missing require for course 2018-02-12 10:40:17 +08:00
Andrew Nicols 6dc3fc7508 Merge branch 'MDL-61305-m33' of https://github.com/sammarshallou/moodle into MOODLE_33_STABLE 2018-02-12 09:09:08 +08:00
Pierre Guinoiseau 8ba2f949d0 MDL-61379 mod_lti: fix a test comparing a hardcoded URL from fixtures
The hardcoded URL from tests/fixtures/ims_cartridge_basic_lti_link.xml
didn't match if TEST_EXTERNAL_FILES_HTTPS_URL was defined, the test
needs to compare with the exact same URL instead of a generated one.
2018-02-12 13:46:48 +13:00
Andrew Nicols e53bde7de2 Merge branch 'MDL-61413_33' of git://github.com/stronk7/moodle into MOODLE_33_STABLE 2018-02-12 08:09:09 +08:00
Marina Glancy aee5a8666a MDL-61150 xmldb: correct path to schema in install.xml 2018-02-11 23:09:03 +01:00
Eloy Lafuente (stronk7) a163049a64 MDL-61150 xmldb: Fix wrong PATH attributes in core 2018-02-11 23:09:03 +01:00
Farhan Karmali 055010a34a MDL-61236 enrol: Course welcome message to be sent from correct contact 2018-02-11 20:49:31 +05:30
Eloy Lafuente (stronk7) abe4724b32 MDL-61413 mod_lti: Use sql_compare_text() for comparing TEXTs 2018-02-11 02:18:58 +01:00
Mark Nelson 163a9d21e5 MDL-61196 message_popup: clean params before returning via WS 2018-02-09 17:37:04 +08:00
Mark Nelson 234d16cfcb MDL-61375 mod_chat: specify the 'eventtype' to avoid duplicate rows 2018-02-09 14:47:17 +08:00
sam marshall e598dc49a7 MDL-61305 Performance: Modinfo cache can get built in parallel
In a busy site it is possible that one user will access the site
while another is building modinfo cache. This can result in the
cache being built several times at once, potentially causing a
performance issue.
2018-02-08 14:50:48 +00:00
David Monllao 1702e66574 weekly release 3.3.4+ 2018-02-08 09:29:12 +01:00
Andrew Nicols 9d8c7eaaa8 Merge branch 'MDL-61377-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-02-07 12:53:02 +08:00
Shamim Rezaie a77941b809 MDL-61377 Core: Fixed faulty warning when using progress_bar 2018-02-07 14:48:39 +11:00
Eloy Lafuente (stronk7) 7fe0d459d6 MDL-52832 quiz: sql fixing couple of incorrect group by uses 2018-02-07 07:09:37 +08:00
Tim Hunt bfe824dd3d MDL-61366 setuplib: safely construct the ajax renderer when needed 2018-02-06 12:12:58 +00:00
David Monllao ad0f68802a Merge branch 'MDL-52832-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-02-06 12:20:19 +01:00
Dan Marsden e3db31ac67 MDL-60421 tool_cohortroles: fix deprecated call. 2018-02-06 10:51:52 +01:00
Eloy Lafuente (stronk7) 00ab44ee52 Merge branch 'MDL-61168-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-05 20:40:36 +01:00
Eloy Lafuente (stronk7) bb89fdcf22 Merge branch 'MDL-61341-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-02-05 20:08:30 +01:00
David Monllao b813a2778b Merge branch 'MDL-61027-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-02-05 11:56:36 +01:00
David Monllao 7e9362481d Merge branch 'MDL-61251-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-02-05 11:50:54 +01:00
David Monllao 407a8d675e Merge branch 'MDL-42764_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-02-05 11:18:54 +01:00
Andrew Nicols 38055cdb22 Merge branch 'MDL-61269_33' of git://github.com/stronk7/moodle into MOODLE_33_STABLE 2018-02-05 17:53:30 +08:00
Andrew Nicols b3c71b12c7 Merge branch 'MDL-51189-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-02-05 15:58:30 +08:00
Eloy Lafuente (stronk7) 5ac4c7f2ba MDL-61269 composer: better license GPL-3.0-or-later
Source: https://spdx.org/licenses/
2018-02-04 19:40:33 +01:00
Sara Arjona 0c8d6093dc MDL-61261 badges: Add email validation during backpack configuration 2018-02-02 11:35:36 +01:00
Andrew Nicols 0ab8ddc56b MDL-61341 theme_boost: Fix usertour zindex calculations 2018-02-02 11:36:46 +08:00
Jun Pataleta 2cda43b3bd MDL-61168 mod_assign: Truncate only the online text submission 2018-02-02 09:21:41 +08:00
Luca Bösch efc06d64e7 MDL-52832 quiz: timeclose in activities block looks after overrides. 2018-02-02 00:00:04 +01:00
Luca Bösch a71eb555c2 MDL-61251 admin: configenablerssfeedsdisabled2 string more correct. 2018-02-01 22:57:20 +01:00
David Monllao 7517f9ea50 weekly release 3.3.4+ 2018-02-01 14:26:40 +01:00
David Monllao 73f8281a01 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-02-01 14:26:39 +01:00
Jake Dallimore 158586680d Merge branch 'MDL-60077-33-fix' of https://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-02-01 14:56:28 +08:00
Andrew Nicols c81ead0adb MDL-60077 tool_usertours: Pull v0.12.2 of usertours for triangle fix 2018-02-01 14:29:06 +08:00
David Mudrák 1ac64fbe83 MDL-61242 repository_equella: Fix missing class repository
The call to the class 'repository' introduced in the commit d05c2ac7cc
didn't fully work and threw: "Exception - Class 'repository' not found".
This fixes the missing library inclusion.
2018-02-01 10:34:39 +08:00
Eloy Lafuente (stronk7) 3111b937ef Merge branch 'MDL-61058-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-01 10:34:38 +08:00
Eloy Lafuente (stronk7) 58c586c3c4 Merge branch 'MDL-61023-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-01 10:34:38 +08:00
Andrew Nicols 9b2b1b5b12 Merge branch 'MDL-61313_33' of git://github.com/dmonllao/moodle into MOODLE_33_STABLE 2018-02-01 10:34:38 +08:00
Eloy Lafuente (stronk7) e9925ef601 Merge branch 'MDL-44612-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-01 10:34:37 +08:00
David Monllao d8aba73bb4 Merge branch 'MDL-60646-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-01 10:34:37 +08:00
David Monllao 4174bcc99c Merge branch 'MDL-60997-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-02-01 10:34:37 +08:00
David Monllao f89874634c Merge branch 'MDL-61260_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-02-01 10:34:36 +08:00
Jake Dallimore 66a13f93e4 Merge branch 'MDL-61253-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-02-01 10:34:36 +08:00
Andrew Nicols 859e9b3394 Merge branch 'MDL-60077-33' of https://github.com/HuongNV13/moodle into MOODLE_33_STABLE 2018-02-01 10:34:36 +08:00
Andrew Nicols 9aae08cc38 Merge branch 'MDL-61250-33' of https://github.com/lucaboesch/moodle into MOODLE_33_STABLE 2018-02-01 10:34:36 +08:00
Adrian Greeve 5608acd0d7 MDL-61322 reports: Reformated the display date to include the year. 2018-02-01 08:30:07 +08:00
AMOS bot 0b13c999e2 Automatically generated installer lang files 2018-02-01 00:06:56 +00:00
AMOS bot fa62cb4137 Automatically generated installer lang files 2018-01-31 00:06:44 +00:00
David Monllao db75ead6fe MDL-61313 behat: Move future events further 2018-01-30 18:17:33 +01:00
AMOS bot 5ae345bdeb Automatically generated installer lang files 2018-01-30 00:06:46 +00:00
Mark Nelson ac8bf02214 MDL-42764 core: added missing string definition
Also changed the string index so it was not
vague. The index 'emailempty' appears as if it
could belong to a validation method for a form.
2018-01-29 19:08:32 +08:00
Huong Nguyen a1a04839eb MDL-60077 User tours: pop-up triangle look bad next to the corners 2018-01-29 10:34:58 +07:00
Mark Nelson d8c58a53d3 MDL-61260 auth_ldap: require /user/profile/lib.php file 2018-01-29 11:31:36 +08:00
Eloy Lafuente (stronk7) 17384a4a8e Merge branch 'wip-MDL-61242-33' of git://github.com/abgreeve/moodle into MOODLE_33_STABLE 2018-01-29 01:41:23 +01:00
Luca Bösch 0a8e683595 MDL-61250 questions: Omit leading space in question preview link 2018-01-25 14:25:53 +01:00
Jun Pataleta 63da6656b9 MDL-60997 core_message: Add replytoname in unit test 2018-01-25 16:48:13 +08:00
Arnaud Trouvé 53556cf240 MDL-60997 messages: add property replytoname 2018-01-25 16:48:12 +08:00
Andrew Nicols a11dae7625 weekly release 3.3.4+ 2018-01-25 15:14:33 +08:00
Andrew Nicols 274d3ca6d5 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-01-25 15:14:29 +08:00
Jake Dallimore 492ddb2bf8 Merge branch 'MDL-60078-33-fix' of https://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-01-25 14:49:00 +08:00
Andrew Nicols 5bb4d629fc MDL-60078 tool_usertours: Adjust accessibility checks for all themes 2018-01-25 12:50:33 +08:00
Eloy Lafuente (stronk7) 9cb82a1530 MDL-61269 behat-extension: bump to fix some caps & defaults 2018-01-25 00:32:28 +01:00
Jun Pataleta a5e434b97e MDL-44612 mod_glossary: Test importing of glossary entries
* And check that the importing of entries is reflected in the recent
activity block.
2018-01-24 16:39:24 +08:00
Jun Pataleta cf9910912f MDL-44612 mod_forum: Confirm forum post listing in recent activity block 2018-01-24 16:39:23 +08:00
Damyon Wiese b2961aa526 MDL-61058 behat: Automate MDLQA-8146
Verify that the keyholder is displayed on the self enrolment page.
2018-01-24 16:37:05 +08:00
Damyon Wiese 48a5afe796 MDL-61023 behat: Automate MDLQA-8158
Verify the general section does not appear in the navigation when it is empty.
2018-01-24 16:35:56 +08:00
Andrew Nicols 83539ba7aa MDL-61234 tool_usertours: Rewrite feature to work with all themes 2018-01-24 10:20:08 +08:00
Andrew Nicols 01484f2289 MDL-61253 repository: Add referenced files to archives 2018-01-23 11:52:13 +08:00
Shamim Rezaie a167de121b MDL-51189 Quiz: Edit overrides when quiz is not available to students
The $active variable should simply be used to dim the text, nothing more.
2018-01-23 10:53:40 +11:00
Eloy Lafuente (stronk7) f058e911cd Merge branch 'MDL-60918-33' of git://github.com/ryanwyllie/moodle into MOODLE_33_STABLE 2018-01-22 20:17:43 +01:00
Eloy Lafuente (stronk7) 06cded2b76 Merge branch 'MDL-58006-33' of git://github.com/zig-moodle/moodle into MOODLE_33_STABLE 2018-01-22 20:00:20 +01:00
Eloy Lafuente (stronk7) df5debbfc4 Merge branch 'MDL-60181-33' of git://github.com/mihailges/moodle into MOODLE_33_STABLE 2018-01-22 12:51:38 +01:00
Shamim Rezaie 1c1c751560 MDL-61027 calendar: Fix datetime profile field issue with non-Gregorian 2018-01-22 19:06:08 +11:00
Mihail Geshoski e6645efea6 MDL-60181 glossary: Glossary rating is displayed wrongly 2018-01-22 13:59:52 +08:00
Zig Tan eedd1437c8 MDL-58006 assign: Reset blindmarking assignments to hidden
Fix to reset blindmarking assigments to hidden as part of Course reset with behat test
2018-01-22 11:37:21 +08:00
Andrew Nicols b1c1aa89ed Merge branch 'MDL-60078-33' of https://github.com/nashtechdev01/moodle into MOODLE_33_STABLE 2018-01-22 11:31:15 +08:00
Eloy Lafuente (stronk7) 8ede8c859e Merge branch 'MDL-61077_33' of git://github.com/timhunt/moodle into MOODLE_33_STABLE 2018-01-22 02:26:19 +01:00
Eloy Lafuente (stronk7) e288c6314f Merge branch 'MDL-61234-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-01-22 02:04:08 +01:00
Eloy Lafuente (stronk7) 4865f138c7 Merge branch 'wip-MDL-61175-MOODLE_33_STABLE' of https://github.com/kwiliarty/moodle into MOODLE_33_STABLE 2018-01-22 01:25:04 +01:00
Eloy Lafuente (stronk7) 9db5265f18 Merge branch 'MDL-61224_33' of git://github.com/markn86/moodle into MOODLE_33_STABLE 2018-01-22 01:23:26 +01:00
Adrian Greeve 5b7ee7d6b3 MDL-61242 repository_equella: Add source key when sending the source.
A thank you to Nelson Cheng for find this issue and suggesting a patch.
2018-01-20 11:02:04 +08:00
Andrew Nicols e1a489362c MDL-61234 tool_usertours: Wrap library calls in pendingjs 2018-01-19 15:55:12 +08:00
AMOS bot 2da5023cd2 Automatically generated installer lang files 2018-01-19 00:07:12 +00:00
Kevin Wiliarty b025f80743 MDL-61175 mod_assign: roll grade-by reminder on restore 2018-01-18 08:42:02 -05:00
Jun Pataleta b65a529086 MDL-60646 user_portfolio: Fix action icons in Show / hide column
* Refactor the code to make it look cleaner and easier to read.
* Fixed incorrect alt-text for the configure icon.
* Fixed missing alt-text for show/hide icon.
2018-01-18 15:27:03 +08:00
Andrew Nicols 68673fb78d weekly release 3.3.4+ 2018-01-18 12:47:57 +08:00
Andrew Nicols 0de71f9432 Merge branch 'install_33_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_33_STABLE 2018-01-18 12:47:54 +08:00
AMOS bot 82815a491e Automatically generated installer lang files 2018-01-17 00:06:38 +00:00
Jun Pataleta 5abcd64852 Merge branch 'MDL-61221-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-01-16 23:01:29 +08:00
KietLy da908a84c3 MDL-60078 User tours accessibility: Tab should go back into the pop-up 2018-01-16 17:36:57 +07:00
Mark Nelson fde9d39538 MDL-61224 core_role: prevent short name from exceeding 100 chars 2018-01-16 18:18:04 +08:00
David Monllao 97cf15c9ad Merge branch 'MDL-61010-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-01-16 09:25:49 +01:00
Adam Olley 6837f2f698 MDL-60918 core_message: update preferences of user behat test 2018-01-16 05:27:10 +00:00
Ryan Wyllie 83b01d7505 MDL-60918 message: use current user in message preference update 2018-01-16 05:27:10 +00:00
Andrew Nicols e9c315ff85 MDL-61221 badges: Ignore site availabilty for behat
Behat sites should not be available publically, and the check against
the backpack API for site availablity can time out in some situations.

We should be testing as though the site _is_ available, as this is the
standard expectation.
2018-01-16 13:23:28 +08:00
David Knuplesch fb4da0de30 MDL-60549 lti: support for moving embedded lti into separate tab 2018-01-16 10:12:24 +08:00
Eloy Lafuente (stronk7) 3cf3e20b77 Merge branch 'MDL-61204-33' of git://github.com/andrewnicols/moodle into MOODLE_33_STABLE 2018-01-16 02:17:08 +01:00
Andrew Nicols 2d6a9a6ef3 MDL-61204 user: Fix random failure in behat
We need to get into the habit of not using usernames like 'student1'
and 'student10' as our matches are non-strict, and the tests become
dependent upon DB sort order.

This change adds a character after the varying value to act as a
delimter for all of these tests.
2018-01-16 08:16:11 +08:00
Andrew Nicols 2a208a32cb MDL-61010 mod_forum: Add unread link to blog view 2018-01-16 08:07:43 +08:00
AMOS bot ba6233ae2c Automatically generated installer lang files 2018-01-16 00:06:49 +00:00
Eloy Lafuente (stronk7) ad2ed52966 Merge branch 'MDL-61081-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-01-16 00:28:01 +01:00
Eloy Lafuente (stronk7) 84bc03313b Merge branch 'MDL-37390-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-01-16 00:25:41 +01:00
Eloy Lafuente (stronk7) 043279b4d9 Merge branch 'MDL-61162-33' of git://github.com/junpataleta/moodle into MOODLE_33_STABLE 2018-01-15 22:58:12 +01:00
Tim Hunt 4a108f79a8 MDL-61077 question stats: make calculations more robust 2018-01-15 16:08:35 +00:00
David Monllao 0c496132cf Merge branch 'MDL-60776-33' of git://github.com/sarjona/moodle into MOODLE_33_STABLE 2018-01-15 10:58:58 +01:00
Eloy Lafuente (stronk7) d251a46588 Merge branch 'MDL-61166-33' of git://github.com/rezaies/moodle into MOODLE_33_STABLE 2018-01-15 10:57:57 +01:00
David Monllao 20c6e3628c Merge branch 'MDL-55382-33' of git://github.com/damyon/moodle into MOODLE_33_STABLE 2018-01-15 10:09:56 +01:00
Shamim Rezaie 6df9abc397 MDL-61166 Groups: Fixed a typo in PHPDoc 2018-01-14 09:23:00 +11:00
Farhan Karmali c16fd22bbc MDL-37390 course: Set startdate properly for approved course
Once a course is approved the startdate is not set properly
This patch sets current midnight date as startdate and leave
enddate to 0
2018-01-12 10:03:43 +01:00
Farhan Karmali b8cf9f06dc MDL-61081 enrol: Start date for courses created by external db
Course created by external db enrolment plugin should have start date as current midnight date
2018-01-12 09:59:28 +01:00
do-you-even-curl 879c847aed MDL-60776 enrol: Fix header for custom fullnamedisplay formats
In case you used a custom fullnamedisplay format that involved anything but spaces (e.g. commas) as delimiters the username header
would be displayed incorrectly and you wouldn't be able to click on the "Firstname" or "Surname" headers to sort according to them.
2018-01-12 09:52:01 +01:00
Jun Pataleta 1b091c789c MDL-61162 mod_forum: Remove unnecessary forum creation step 2018-01-08 10:58:20 +08:00
Mihail Geshoski 15646264c4 MDL-61153 lesson: Inconsistent column sizing in detailed statistics 2018-01-04 15:49:51 +08:00
Damyon Wiese d716aa1587 MDL-55382 assign: Sort editpdf quick list 2017-12-15 14:58:00 +08:00
Ann Adamcik 287089b1a2 MDL-58697: Only get group submission if enabled 2017-12-01 12:48:44 -07:00
1442 changed files with 97277 additions and 1966 deletions
+1 -1
View File
@@ -249,7 +249,7 @@ script:
- >
if [ "$TASK" = 'PHPUNIT' ];
then
vendor/bin/phpunit;
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
fi
- >
+4 -2
View File
@@ -75,7 +75,7 @@ if ($data = data_submitted() and confirm_sesskey()) {
if ($PAGE->user_allowed_editing() && $adminediting != -1) {
$USER->editing = $adminediting;
}
$buttons = null;
if ($PAGE->user_allowed_editing()) {
$url = clone($PAGE->url);
if ($PAGE->user_is_editing()) {
@@ -129,7 +129,9 @@ if ($savebutton) {
$visiblepathtosection = array_reverse($settingspage->visiblepath);
$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection));
$PAGE->set_heading($SITE->fullname);
$PAGE->set_button($buttons);
if ($buttons) {
$PAGE->set_button($buttons);
}
echo $OUTPUT->header();
+41
View File
@@ -0,0 +1,41 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for core_admin.
*
* @package core_admin
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for core_admin implementing null_provider.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
+2 -3
View File
@@ -37,7 +37,7 @@ require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
admin_externalpage_setup('registrationhubs');
$renderer = $PAGE->get_renderer('core', 'register');
$renderer = $PAGE->get_renderer('core', 'admin');
$unregistration = optional_param('unregistration', 0, PARAM_INT);
$cleanregdata = optional_param('cleanregdata', 0, PARAM_BOOL);
@@ -181,8 +181,7 @@ if (empty($cancel) and $unregistration and !$confirm) {
echo $OUTPUT->header();
//check if the site is registered on Moodle.org and display a message about registering on MOOCH
$adminrenderer = $PAGE->get_renderer('core', 'admin');
echo $adminrenderer->warn_if_not_registered();
echo $renderer->warn_if_not_registered();
//do not check sesskey if confirm = false because this script is linked into email message
if (!empty($errormessage)) {
+1 -1
View File
@@ -195,7 +195,7 @@ if ($huburl == HUB_MOODLEORGHUBURL) {
echo $OUTPUT->notification($registrationmessage, $notificationtype);
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
$renderer = $PAGE->get_renderer('core', 'register');
$renderer = $PAGE->get_renderer('core', 'admin');
echo $renderer->moodleorg_registration_message();
}
-95
View File
@@ -1,95 +0,0 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// This file is part of Moodle - http://moodle.org/ //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// //
// Moodle is free software: you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License, or //
// (at your option) any later version. //
// //
// Moodle is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Registration renderer.
* @package moodle
* @subpackage registration
* @copyright 2010 Moodle Pty Ltd (http://moodle.com)
* @author Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_register_renderer extends plugin_renderer_base {
/**
* Display message about the benefits of registering on Moodle.org
*
* @return string
*/
public function moodleorg_registration_message() {
$moodleorgstatslink = html_writer::link('http://moodle.net/stats',
get_string('statsmoodleorg', 'admin'),
array('target' => '_blank'));
$moodleorgregmsg = get_string('registermoodleorg', 'admin');
$items = array(get_string('registermoodleorgli1', 'admin'),
get_string('registermoodleorgli2', 'admin', $moodleorgstatslink));
$moodleorgregmsg .= html_writer::alist($items);
return $moodleorgregmsg;
}
/**
* Display a box message confirming a site registration (add or update)
* @param string $confirmationmessage
* @return string
*/
public function registration_confirmation($confirmationmessage) {
$linktositelist = html_writer::tag('a', get_string('sitelist', 'hub'),
array('href' => new moodle_url('/local/hub/index.php')));
$message = $confirmationmessage . html_writer::empty_tag('br') . $linktositelist;
return $this->output->box($message);
}
/**
* Display the listing of registered on hub
*/
public function registeredonhublisting($hubs) {
global $CFG;
$table = new html_table();
$table->head = array(get_string('hub', 'hub'), get_string('operation', 'hub'));
$table->size = array('80%', '20%');
foreach ($hubs as $hub) {
if ($hub->huburl == HUB_MOODLEORGHUBURL) {
$hub->hubname = get_string('registeredmoodleorg', 'hub', $hub->hubname);
}
$hublink = html_writer::tag('a', $hub->hubname, array('href' => $hub->huburl));
$hublinkcell = html_writer::tag('div', $hublink, array('class' => 'registeredhubrow'));
$unregisterhuburl = new moodle_url("/" . $CFG->admin . "/registration/index.php",
array('sesskey' => sesskey(), 'huburl' => $hub->huburl,
'unregistration' => 1));
$unregisterbutton = new single_button($unregisterhuburl,
get_string('unregister', 'hub'));
$unregisterbutton->class = 'centeredbutton';
$unregisterbuttonhtml = $this->output->render($unregisterbutton);
//add button cells
$cells = array($hublinkcell, $unregisterbuttonhtml);
$row = new html_table_row($cells);
$table->data[] = $row;
}
return html_writer::table($table);
}
}
+65
View File
@@ -2033,4 +2033,69 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning(get_string('legacylogginginuse'));
}
}
/**
* Display message about the benefits of registering on Moodle.org
*
* @return string
*/
public function moodleorg_registration_message() {
$moodleorgstatslink = html_writer::link('http://moodle.net/stats',
get_string('statsmoodleorg', 'admin'),
array('target' => '_blank'));
$moodleorgregmsg = get_string('registermoodleorg', 'admin');
$items = array(get_string('registermoodleorgli1', 'admin'),
get_string('registermoodleorgli2', 'admin', $moodleorgstatslink));
$moodleorgregmsg .= html_writer::alist($items);
return $moodleorgregmsg;
}
/**
* Display a box message confirming a site registration (add or update)
* @param string $confirmationmessage
* @return string
*/
public function registration_confirmation($confirmationmessage) {
$linktositelist = html_writer::tag('a', get_string('sitelist', 'hub'),
array('href' => new moodle_url('/local/hub/index.php')));
$message = $confirmationmessage . html_writer::empty_tag('br') . $linktositelist;
return $this->output->box($message);
}
/**
* Display the listing of registered on hub
*
* @param stdClass[] $hubs
* @return string
*/
public function registeredonhublisting($hubs) {
global $CFG;
$table = new html_table();
$table->head = array(get_string('hub', 'hub'), get_string('operation', 'hub'));
$table->size = array('80%', '20%');
foreach ($hubs as $hub) {
if ($hub->huburl == HUB_MOODLEORGHUBURL) {
$hub->hubname = get_string('registeredmoodleorg', 'hub', $hub->hubname);
}
$hublink = html_writer::tag('a', $hub->hubname, array('href' => $hub->huburl));
$hublinkcell = html_writer::tag('div', $hublink, array('class' => 'registeredhubrow'));
$unregisterhuburl = new moodle_url("/" . $CFG->admin . "/registration/index.php",
array('sesskey' => sesskey(), 'huburl' => $hub->huburl,
'unregistration' => 1));
$unregisterbutton = new single_button($unregisterhuburl,
get_string('unregister', 'hub'));
$unregisterbutton->class = 'centeredbutton';
$unregisterbuttonhtml = $this->output->render($unregisterbutton);
// Add button cells.
$cells = array($hublinkcell, $unregisterbuttonhtml);
$row = new html_table_row($cells);
$table->data[] = $row;
}
return html_writer::table($table);
}
}
+1 -1
View File
@@ -245,7 +245,7 @@ if ($roleid) {
$select = new single_select($PAGE->url, 'roleid', $nameswithcounts, $roleid, null);
$select->label = get_string('assignanotherrole', 'core_role');
echo $OUTPUT->render($select);
echo '<p><a href="' . $PAGE->url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
echo '<p><a href="' . $url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
echo '</div>';
} else if (empty($assignableroles)) {
@@ -100,6 +100,8 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$this->role->shortname = core_text::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
if (empty($this->role->shortname)) {
$this->errors['shortname'] = get_string('errorbadroleshortname', 'core_role');
} else if (core_text::strlen($this->role->shortname) > 100) { // Check if it exceeds the max of 100 characters.
$this->errors['shortname'] = get_string('errorroleshortnametoolong', 'core_role');
}
}
if ($DB->record_exists_select('role', 'shortname = ? and id <> ?', array($this->role->shortname, $this->roleid))) {
@@ -476,7 +478,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
}
protected function get_shortname_field($id) {
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->shortname) . '"' .
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="100" value="' . s($this->role->shortname) . '"' .
' class="form-control"/>';
}
+379
View File
@@ -0,0 +1,379 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for core_role.
*
* @package core_role
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_role\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\contextlist;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\transform;
use \core_privacy\local\request\writer;
/**
* Privacy provider for core_role.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\subsystem\provider,
\core_privacy\local\request\subsystem\plugin_provider,
\core_privacy\local\request\user_preference_provider {
/**
* Get information about the user data stored by this plugin.
*
* @param collection $collection An object for storing metadata.
* @return collection The metadata.
*/
public static function get_metadata(collection $collection) {
$rolecapabilities = [
'roleid' => 'privacy:metadata:role_capabilities:roleid',
'capability' => 'privacy:metadata:role_capabilities:capability',
'permission' => 'privacy:metadata:role_capabilities:permission',
'timemodified' => 'privacy:metadata:role_capabilities:timemodified',
'modifierid' => 'privacy:metadata:role_capabilities:modifierid'
];
$roleassignments = [
'roleid' => 'privacy:metadata:role_assignments:roleid',
'userid' => 'privacy:metadata:role_assignments:userid',
'timemodified' => 'privacy:metadata:role_assignments:timemodified',
'modifierid' => 'privacy:metadata:role_assignments:modifierid',
'component' => 'privacy:metadata:role_assignments:component',
'itemid' => 'privacy:metadata:role_assignments:itemid'
];
$collection->add_database_table('role_capabilities', $rolecapabilities,
'privacy:metadata:role_capabilities:tableexplanation');
$collection->add_database_table('role_assignments', $roleassignments,
'privacy:metadata:role_assignments:tableexplanation');
$collection->add_user_preference('definerole_showadvanced',
'privacy:metadata:preference:showadvanced');
return $collection;
}
/**
* Export all user preferences for the plugin.
*
* @param int $userid The userid of the user whose data is to be exported.
*/
public static function export_user_preferences($userid) {
$showadvanced = get_user_preferences('definerole_showadvanced', null, $userid);
if ($showadvanced !== null) {
writer::export_user_preference('core_role',
'definerole_showadvanced',
transform::yesno($showadvanced),
get_string('privacy:metadata:preference:showadvanced', 'core_role')
);
}
}
/**
* Return all contexts for this userid.
*
* @param int $userid The user ID.
* @return contextlist The list of context IDs.
*/
public static function get_contexts_for_userid($userid) {
global $DB;
$contextlist = new contextlist();
// The role_capabilities table contains user data.
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$sql = "SELECT ctx.id
FROM {context} ctx
JOIN {role_capabilities} rc
ON rc.contextid = ctx.id
AND ((ctx.contextlevel {$insql} AND rc.modifierid = :modifierid)
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))";
$params = [
'modifierid' => $userid,
'contextlevel' => CONTEXT_USER,
'userid' => $userid
];
$params += $inparams;
$contextlist->add_from_sql($sql, $params);
// The role_assignments table contains user data.
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$params = [
'userid' => $userid,
'modifierid' => $userid
];
$params += $inparams;
$sql = "SELECT ctx.id
FROM {role_assignments} ra
JOIN {context} ctx
ON ctx.id = ra.contextid
AND ctx.contextlevel {$insql}
WHERE (ra.userid = :userid
OR ra.modifierid = :modifierid)
AND ra.component != 'tool_cohortroles'";
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The list of approved contexts for a user.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
if (empty($contextlist)) {
return;
}
$rolesnames = self::get_roles_name();
$userid = $contextlist->get_user()->id;
$ctxfields = \context_helper::get_preload_record_columns_sql('ctx');
list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
// Role Assignments export data.
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, $ctxfields
FROM {role_assignments} ra
JOIN {context} ctx
ON ctx.id = ra.contextid
AND ctx.contextlevel {$inctxsql}
AND (ra.userid = :userid OR ra.modifierid = :modifierid)
AND ra.component != 'tool_cohortroles'
JOIN {role} r
ON r.id = ra.roleid
WHERE ctx.id {$insql}";
$params = ['userid' => $userid, 'modifierid' => $userid];
$params += $inparams;
$params += $ctxparams;
$assignments = $DB->get_recordset_sql($sql, $params);
foreach ($assignments as $assignment) {
\context_helper::preload_from_record($assignment);
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
'timemodified' => transform::datetime($assignment->timemodified),
'userid' => transform::user($assignment->userid),
'modifierid' => transform::user($assignment->modifierid)
];
}
$assignments->close();
if (!empty($alldata)) {
array_walk($alldata, function($roledata, $contextid) {
$context = \context::instance_by_id($contextid);
array_walk($roledata, function($data, $rolename) use ($context) {
writer::with_context($context)->export_data(
[get_string('privacy:metadata:role_assignments', 'core_role'), $rolename],
(object)$data);
});
});
unset($alldata);
}
// Role Capabilities export data.
$strpermissions = self::get_permissions_name();
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$sql = "SELECT rc.id, rc.contextid, rc.capability, rc.permission, rc.timemodified, rc.roleid, $ctxfields
FROM {context} ctx
JOIN {role_capabilities} rc
ON rc.contextid = ctx.id
AND ((ctx.contextlevel {$inctxsql} AND rc.modifierid = :modifierid)
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))
WHERE ctx.id {$insql}";
$params = [
'modifierid' => $userid,
'contextlevel' => CONTEXT_USER,
'userid' => $userid
];
$params += $inparams;
$params += $ctxparams;
$capabilities = $DB->get_recordset_sql($sql, $params);
foreach ($capabilities as $capability) {
\context_helper::preload_from_record($capability);
$alldata[$capability->contextid][$rolesnames[$capability->roleid]][] = (object)[
'timemodified' => transform::datetime($capability->timemodified),
'capability' => $capability->capability,
'permission' => $strpermissions[$capability->permission]
];
}
$capabilities->close();
if (!empty($alldata)) {
array_walk($alldata, function($capdata, $contextid) {
$context = \context::instance_by_id($contextid);
array_walk($capdata, function($data, $rolename) use ($context) {
writer::with_context($context)->export_data(
[get_string('privacy:metadata:role_capabilities', 'core_role'), $rolename],
(object)$data);
});
});
}
}
/**
* Exports the data relating to tool_cohortroles component on role assignments by
* Assign user roles to cohort feature.
*
* @param int $userid The user ID.
*/
public static function export_user_role_to_cohort($userid) {
global $DB;
$rolesnames = self::get_roles_name();
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, r.id as roleid
FROM {role_assignments} ra
JOIN {context} ctx
ON ctx.id = ra.contextid
AND ctx.contextlevel = :contextlevel
AND ra.component = 'tool_cohortroles'
JOIN {role} r
ON r.id = ra.roleid
WHERE ctx.instanceid = :instanceid
OR ra.userid = :userid";
$params = ['userid' => $userid, 'instanceid' => $userid, 'contextlevel' => CONTEXT_USER];
$assignments = $DB->get_recordset_sql($sql, $params);
foreach ($assignments as $assignment) {
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
'timemodified' => transform::datetime($assignment->timemodified),
'userid' => transform::user($assignment->userid),
'modifierid' => transform::user($assignment->modifierid)
];
}
$assignments->close();
if (!empty($alldata)) {
array_walk($alldata, function($roledata, $contextid) {
$context = \context::instance_by_id($contextid);
array_walk($roledata, function($data, $rolename) use ($context) {
writer::with_context($context)->export_related_data(
[get_string('privacy:metadata:role_cohortroles', 'core_role'), $rolename], 'cohortroles',
(object)$data);
});
});
}
}
/**
* Delete all user data for this context.
*
* @param \context $context The context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
global $DB;
// Don't remove data from role_capabilities.
// Because this data affects the whole Moodle, there are override capabilities.
// Don't belong to the modifier user.
// Remove data from role_assignments.
$DB->delete_records('role_assignments', ['contextid' => $context->id]);
}
/**
* Delete all user data for this user only.
*
* @param approved_contextlist $contextlist The list of approved contexts for a user.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
// Don't remove data from role_capabilities.
// Because this data affects the whole Moodle, there are override capabilities.
// Don't belong to the modifier user.
// Remove data from role_assignments.
if (empty($contextlist->count())) {
return;
}
$userid = $contextlist->get_user()->id;
foreach ($contextlist->get_contexts() as $context) {
// Only delete the roles assignments where the user is assigned in all contexts.
$DB->delete_records('role_assignments', ['userid' => $userid, 'contextid' => $context->id]);
}
}
/**
* Delete user entries in role_assignments related to the feature
* Assign user roles to cohort feature.
*
* @param int $userid The user ID.
*/
public static function delete_user_role_to_cohort($userid) {
global $DB;
// Delete entries where userid is a mentor by tool_cohortroles.
$DB->delete_records('role_assignments', ['userid' => $userid, 'component' => 'tool_cohortroles']);
}
/**
* Get all the localised roles name in a simple array.
*
* @return array Array of name of the roles by roleid.
*/
protected static function get_roles_name() {
$roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
$rolesnames = array();
foreach ($roles as $role) {
$rolesnames[$role->id] = $role->localname;
}
return $rolesnames;
}
/**
* Get all the permissions name in a simple array.
*
* @return array Array of permissions name.
*/
protected static function get_permissions_name() {
$strpermissions = array(
CAP_INHERIT => get_string('inherit', 'role'),
CAP_ALLOW => get_string('allow', 'role'),
CAP_PREVENT => get_string('prevent', 'role'),
CAP_PROHIBIT => get_string('prohibit', 'role')
);
return $strpermissions;
}
}
+477
View File
@@ -0,0 +1,477 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy test for core_role
*
* @package core_role
* @category test
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use \core_role\privacy\provider;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\writer;
use \core_privacy\tests\provider_testcase;
use \core_privacy\local\request\transform;
use \tool_cohortroles\api;
/**
* Privacy test for core_role
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_role_privacy_testcase extends provider_testcase {
/**
* Test to check export_user_preferences.
* returns user preferences data.
*/
public function test_export_user_preferences() {
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$showadvanced = 1;
set_user_preference('definerole_showadvanced', $showadvanced);
provider::export_user_preferences($user->id);
$writer = writer::with_context(\context_system::instance());
$prefs = $writer->get_user_preferences('core_role');
$this->assertEquals(transform::yesno($showadvanced), transform::yesno($prefs->definerole_showadvanced->value));
$this->assertEquals(get_string('privacy:metadata:preference:showadvanced', 'core_role'),
$prefs->definerole_showadvanced->description);
}
/**
* Check all contexts are returned if there is any user data for this user.
*/
public function test_get_contexts_for_userid() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$this->assertEmpty(provider::get_contexts_for_userid($user->id));
$user2 = $this->getDataGenerator()->create_user();
$usercontext2 = \context_user::instance($user2->id);
$course = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$coursecat = $this->getDataGenerator()->create_category();
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
$cmcontext = \context_module::instance($cm->cmid);
$page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
$cmcontext2 = \context_module::instance($page->cmid);
$coursecontext = \context_course::instance($course->id);
$coursecontext2 = \context_course::instance($course2->id);
$coursecatcontext = \context_coursecat::instance($coursecat->id);
$systemcontext = \context_system::instance();
$block = $this->getDataGenerator()->create_block('online_users');
$blockcontext = \context_block::instance($block->id);
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
// Role assignments, where the user is assigned.
role_assign($student->id, $user->id, $cmcontext2->id);
role_assign($student->id, $user->id, $coursecontext2->id);
role_assign($student->id, $user->id, $blockcontext->id);
role_assign($manager->id, $user->id, $usercontext2->id);
// Role assignments, where the user makes assignments.
$this->setUser($user);
role_assign($student->id, $user2->id, $coursecontext->id);
role_assign($manager->id, $user2->id, $coursecatcontext->id);
role_assign($manager->id, $user2->id, $systemcontext->id);
// Role capabilities.
$this->setUser($user);
$result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $cmcontext->id);
$contextlist = provider::get_contexts_for_userid($user->id)->get_contextids();
$this->assertCount(8, $contextlist);
$this->assertTrue(in_array($cmcontext->id, $contextlist));
}
/**
* Test that user data is exported correctly.
*/
public function test_export_user_data() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext2 = \context_user::instance($user2->id);
$course = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$coursecat = $this->getDataGenerator()->create_category();
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
$cmcontext = \context_module::instance($cm->cmid);
$page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
$cmcontext2 = \context_module::instance($page->cmid);
$coursecontext = \context_course::instance($course->id);
$coursecontext2 = \context_course::instance($course2->id);
$coursecatcontext = \context_coursecat::instance($coursecat->id);
$systemcontext = \context_system::instance();
$block = $this->getDataGenerator()->create_block('online_users');
$blockcontext = \context_block::instance($block->id);
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
$rolesnames = self::get_roles_name();
$subcontextstudent = [
get_string('privacy:metadata:role_assignments', 'core_role'),
$rolesnames[$student->id]
];
$subcontextmanager = [
get_string('privacy:metadata:role_assignments', 'core_role'),
$rolesnames[$manager->id]
];
$subcontextrc = [
get_string('privacy:metadata:role_capabilities', 'core_role'),
$rolesnames[$student->id]
];
// Test over role assignments.
// Where the user is assigned.
role_assign($student->id, $user->id, $cmcontext2->id);
role_assign($student->id, $user->id, $coursecontext2->id);
role_assign($student->id, $user->id, $blockcontext->id);
role_assign($manager->id, $user->id, $usercontext2->id);
// Where the user makes assignments.
$this->setUser($user);
role_assign($manager->id, $user2->id, $coursecatcontext->id);
role_assign($manager->id, $user2->id, $systemcontext->id);
// Test overridable roles in module, course, category, user, system and block.
assign_capability('moodle/backup:backupactivity', CAP_ALLOW, $student->id, $cmcontext->id, true);
assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $coursecontext->id, true);
assign_capability('moodle/category:manage', CAP_ALLOW, $student->id, $coursecatcontext->id, true);
assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $systemcontext->id, true);
assign_capability('moodle/block:edit', CAP_ALLOW, $student->id, $blockcontext->id, true);
assign_capability('moodle/competency:evidencedelete', CAP_ALLOW, $student->id, $usercontext2->id, true);
// Retrieve the user's context ids.
$contextlist = provider::get_contexts_for_userid($user->id);
$approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
$strpermissions = array(
CAP_INHERIT => get_string('inherit', 'role'),
CAP_ALLOW => get_string('allow', 'role'),
CAP_PREVENT => get_string('prevent', 'role'),
CAP_PROHIBIT => get_string('prohibit', 'role')
);
// Retrieve role capabilities and role assignments.
provider::export_user_data($approvedcontextlist);
foreach ($contextlist as $context) {
$writer = writer::with_context($context);
$this->assertTrue($writer->has_any_data());
if ($context->contextlevel == CONTEXT_MODULE) {
if ($data = $writer->get_data($subcontextstudent)) {
$this->assertEquals($user->id, reset($data)->userid);
}
if ($data = $writer->get_data($subcontextrc)) {
$this->assertEquals('moodle/backup:backupactivity', reset($data)->capability);
$this->assertEquals($strpermissions[CAP_ALLOW], reset($data)->permission);
}
}
if ($context->contextlevel == CONTEXT_COURSE) {
if ($data = $writer->get_data($subcontextstudent)) {
$this->assertEquals($user->id, reset($data)->userid);
}
if ($data = $writer->get_data($subcontextrc)) {
$this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
}
}
if ($context->contextlevel == CONTEXT_COURSECAT) {
if ($data = $writer->get_data($subcontextmanager)) {
$this->assertEquals($user->id, reset($data)->modifierid);
}
if ($data = $writer->get_data($subcontextrc)) {
$this->assertEquals('moodle/category:manage', reset($data)->capability);
}
}
if ($context->contextlevel == CONTEXT_SYSTEM) {
if ($data = $writer->get_data($subcontextmanager)) {
$this->assertEquals($user->id, reset($data)->modifierid);
}
if ($data = $writer->get_data($subcontextrc)) {
$this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
}
}
if ($context->contextlevel == CONTEXT_BLOCK) {
if ($data = $writer->get_data($subcontextstudent)) {
$this->assertEquals($user->id, reset($data)->userid);
}
if ($data = $writer->get_data($subcontextrc)) {
$this->assertEquals('moodle/block:edit', reset($data)->capability);
}
}
if ($context->contextlevel == CONTEXT_USER) {
if ($data = $writer->get_data($subcontextmanager)) {
$this->assertEquals($user->id, reset($data)->userid);
}
if ($data = $writer->get_data($subcontextrc)) {
$this->assertEquals('moodle/competency:evidencedelete', reset($data)->capability);
}
}
}
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext2 = \context_user::instance($user2->id);
$user3 = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$coursecat = $this->getDataGenerator()->create_category();
$coursecatcontext = \context_coursecat::instance($coursecat->id);
$systemcontext = \context_system::instance();
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
$cmcontext = \context_module::instance($cm->cmid);
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
$block = $this->getDataGenerator()->create_block('online_users');
$blockcontext = \context_block::instance($block->id);
// Role assignments CONTEXT_COURSE.
role_assign($student->id, $user->id, $coursecontext->id);
role_assign($student->id, $user2->id, $coursecontext->id);
role_assign($student->id, $user3->id, $coursecontext->id);
$count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
$this->assertEquals(3, $count);
// Role assignments CONTEXT_COURSECAT.
role_assign($student->id, $user2->id, $coursecatcontext->id);
role_assign($student->id, $user3->id, $coursecatcontext->id);
$count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
$this->assertEquals(2, $count);
// Role assignments CONTEXT_SYSTEM.
role_assign($student->id, $user->id, $systemcontext->id);
$count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
$this->assertEquals(1, $count);
// Role assignments CONTEXT_MODULE.
role_assign($student->id, $user->id, $cmcontext->id);
$count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
$this->assertEquals(1, $count);
// Role assigments CONTEXT_BLOCK.
role_assign($student->id, $user->id, $blockcontext->id);
$count = $DB->count_records('role_assignments', ['contextid' => $blockcontext->id]);
$this->assertEquals(1, $count);
// Role assigments CONTEXT_USER.
role_assign($manager->id, $user->id, $usercontext2->id);
$count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
$this->assertEquals(1, $count);
// Delete data based on CONTEXT_COURSE context.
provider::delete_data_for_all_users_in_context($coursecontext);
// After deletion, the role_assignments entries for this context should have been deleted.
$count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
$this->assertEquals(0, $count);
// Check it is not removing data on other contexts.
$count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
$this->assertEquals(2, $count);
$count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
$this->assertEquals(1, $count);
$count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
$this->assertEquals(1, $count);
// Delete data based on CONTEXT_COURSECAT context.
provider::delete_data_for_all_users_in_context($coursecatcontext);
// After deletion, the role_assignments entries for this context should have been deleted.
$count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
$this->assertEquals(0, $count);
// Delete data based on CONTEXT_SYSTEM context.
provider::delete_data_for_all_users_in_context($systemcontext);
// After deletion, the role_assignments entries for this context should have been deleted.
$count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
$this->assertEquals(0, $count);
// Delete data based on CONTEXT_MODULE context.
provider::delete_data_for_all_users_in_context($cmcontext);
// After deletion, the role_assignments entries for this context should have been deleted.
$count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
$this->assertEquals(0, $count);
// Delete data based on CONTEXT_BLOCK context.
provider::delete_data_for_all_users_in_context($usercontext2);
// After deletion, the role_assignments entries for this context should have been deleted.
$count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
$this->assertEquals(0, $count);
}
/**
* Test for provider::delete_data_for_user().
*/
public function test_delete_data_for_user() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext2 = \context_user::instance($user2->id);
$user3 = $this->getDataGenerator()->create_user();
$usercontext3 = \context_user::instance($user3->id);
$course = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course3 = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
$coursecontext2 = \context_course::instance($course2->id);
$coursecontext3 = \context_course::instance($course3->id);
$coursecat = $this->getDataGenerator()->create_category();
$coursecatcontext = \context_coursecat::instance($coursecat->id);
$systemcontext = \context_system::instance();
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
$cmcontext = \context_module::instance($cm->cmid);
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
$block = $this->getDataGenerator()->create_block('online_users');
$blockcontext = \context_block::instance($block->id);
// Role assignments, Where the user is assigned.
role_assign($student->id, $user->id, $coursecontext->id);
role_assign($student->id, $user->id, $coursecontext2->id);
role_assign($student->id, $user->id, $coursecatcontext->id);
role_assign($student->id, $user->id, $cmcontext->id);
role_assign($student->id, $user->id, $systemcontext->id);
role_assign($student->id, $user->id, $blockcontext->id);
role_assign($manager->id, $user->id, $usercontext2->id);
role_assign($manager->id, $user->id, $usercontext3->id);
$count = $DB->count_records('role_assignments', ['userid' => $user->id]);
$this->assertEquals(8, $count);
// Role assignments, where the user makes assignments.
$this->setUser($user);
role_assign($student->id, $user2->id, $coursecontext3->id);
role_assign($student->id, $user3->id, $coursecontext3->id);
$count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
$this->assertEquals(2, $count);
$contextlist = provider::get_contexts_for_userid($user->id);
$approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
provider::delete_data_for_user($approvedcontextlist);
// After deletion, the role_assignments assigned to the user should have been deleted.
$count = $DB->count_records('role_assignments', ['userid' => $user->id]);
$this->assertEquals(0, $count);
// After deletion, the role_assignments assigned by the user should not have been deleted.
$count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
$this->assertEquals(2, $count);
}
/**
* Export for a user with a key against a script where no instance is specified.
*/
public function test_export_user_role_to_cohort() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Assign user roles to cohort.
$user = $this->getDataGenerator()->create_user();
$contextuser = \context_user::instance($user->id);
$teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
$cohort = $this->getDataGenerator()->create_cohort();
$userassignover = $this->getDataGenerator()->create_user();
$contextuserassignover = \context_user::instance($userassignover->id);
cohort_add_member($cohort->id, $userassignover->id);
$this->setAdminUser();
$params = (object) array(
'userid' => $user->id,
'roleid' => $teacher->id,
'cohortid' => $cohort->id
);
api::create_cohort_role_assignment($params);
api::sync_all_cohort_roles();
$rolesnames = self::get_roles_name();
$subcontextteacher = [
get_string('privacy:metadata:role_cohortroles', 'core_role'),
$rolesnames[$teacher->id]
];
// Test User is assigned role teacher to cohort.
provider::export_user_role_to_cohort($user->id);
$writer = writer::with_context($contextuserassignover);
$this->assertTrue($writer->has_any_data());
$exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
$this->assertEquals($user->id, reset($exported)->userid);
// Test User is member of a cohort which User2 is assigned to role to this cohort.
$user2 = $this->getDataGenerator()->create_user();
$cohort2 = $this->getDataGenerator()->create_cohort();
cohort_add_member($cohort2->id, $user->id);
$params = (object) array(
'userid' => $user2->id,
'roleid' => $teacher->id,
'cohortid' => $cohort2->id
);
api::create_cohort_role_assignment($params);
api::sync_all_cohort_roles();
provider::export_user_role_to_cohort($user->id);
$writer = writer::with_context($contextuser);
$this->assertTrue($writer->has_any_data());
$exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
$this->assertEquals($user2->id, reset($exported)->userid);
}
/**
* Test for provider::delete_user_role_to_cohort().
*/
public function test_delete_user_role_to_cohort() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Assign user roles to cohort.
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
$cohort = $this->getDataGenerator()->create_cohort();
cohort_add_member($cohort->id, $user2->id);
cohort_add_member($cohort->id, $user3->id);
cohort_add_member($cohort->id, $user4->id);
$this->setAdminUser();
$params = (object) array(
'userid' => $user->id,
'roleid' => $teacher->id,
'cohortid' => $cohort->id
);
api::create_cohort_role_assignment($params);
api::sync_all_cohort_roles();
$count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
$this->assertEquals(3, $count);
provider::delete_user_role_to_cohort($user->id);
$count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
$this->assertEquals(0, $count);
}
/**
* Supoort function to get all the localised roles name
* in a simple array for testing.
*
* @return array Array of name of the roles by roleid.
*/
protected static function get_roles_name() {
$roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
$rolesnames = array();
foreach ($roles as $role) {
$rolesnames[$role->id] = $role->localname;
}
return $rolesnames;
}
}
+1 -1
View File
@@ -199,7 +199,7 @@ preferences,moodle|/user/preferences.php|preferences',
// "documentation" settingpage
$temp = new admin_settingpage('documentation', new lang_string('moodledocs'));
$temp->add(new admin_setting_configtext('docroot', new lang_string('docroot', 'admin'), new lang_string('configdocroot', 'admin'), 'http://docs.moodle.org', PARAM_URL));
$temp->add(new admin_setting_configtext('docroot', new lang_string('docroot', 'admin'), new lang_string('configdocroot', 'admin'), 'https://docs.moodle.org', PARAM_URL));
$ltemp = array('' => get_string('forceno'));
$ltemp += get_string_manager()->get_list_of_translations(true);
$temp->add(new admin_setting_configselect('doclang', get_string('doclang', 'admin'), get_string('configdoclang', 'admin'), '', $ltemp));
+3 -1
View File
@@ -28,7 +28,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$ADMIN->add('development', $temp);
// "Profiling" settingpage (conditionally if the 'xhprof' extension is available only).
$xhprofenabled = extension_loaded('xhprof') || extension_loaded('tideways');
$xhprofenabled = extension_loaded('tideways_xhprof');
$xhprofenabled = $xhprofenabled || extension_loaded('tideways');
$xhprofenabled = $xhprofenabled || extension_loaded('xhprof');
$temp = new admin_settingpage('profiling', new lang_string('profiling', 'admin'), 'moodle/site:config', !$xhprofenabled);
// Main profiling switch.
$temp->add(new admin_setting_configcheckbox('profilingenabled', new lang_string('profilingenabled', 'admin'), new lang_string('profilingenabled_help', 'admin'), false));
+1 -2
View File
@@ -49,8 +49,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
3600 => new lang_string('numminutes', '', 60))));
$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
$temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'admin'), new lang_string('sitepolicy_help', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'admin'), new lang_string('sitepolicyguest_help', 'admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('keeptagnamecase', new lang_string('keeptagnamecase','admin'),new lang_string('configkeeptagnamecase', 'admin'),'1'));
+46
View File
@@ -4,6 +4,7 @@
$ADMIN->add('users', new admin_category('accounts', new lang_string('accounts', 'admin')));
$ADMIN->add('users', new admin_category('roles', new lang_string('permissions', 'role')));
$ADMIN->add('users', new admin_category('privacy', new lang_string('privacyandpolicies', 'admin')));
if ($hassiteconfig
or has_capability('moodle/user:create', $systemcontext)
@@ -212,3 +213,48 @@ if ($hassiteconfig
$ADMIN->add('roles', new admin_externalpage('checkpermissions', new lang_string('checkglobalpermissions', 'role'), "$CFG->wwwroot/$CFG->admin/roles/check.php?contextid=".$systemcontext->id, array('moodle/role:assign', 'moodle/role:safeoverride', 'moodle/role:override', 'moodle/role:manage')));
} // end of speedup
// Privacy settings.
if ($hassiteconfig) {
$temp = new admin_settingpage('privacysettings', new lang_string('privacysettings', 'admin'));
$options = array(
0 => get_string('no'),
1 => get_string('yes')
);
$url = new moodle_url('/admin/settings.php?section=supportcontact');
$url = $url->out();
$setting = new admin_setting_configselect('agedigitalconsentverification',
new lang_string('agedigitalconsentverification', 'admin'),
new lang_string('agedigitalconsentverification_desc', 'admin', $url), 0, $options);
$setting->set_force_ltr(true);
$temp->add($setting);
// See {@link https://gdpr-info.eu/art-8-gdpr/}.
$ageofdigitalconsentmap = implode(PHP_EOL, [
'*, 16',
'AT, 14',
'ES, 14',
'US, 13'
]);
$setting = new admin_setting_agedigitalconsentmap('agedigitalconsentmap',
new lang_string('ageofdigitalconsentmap', 'admin'),
new lang_string('ageofdigitalconsentmap_desc', 'admin'),
$ageofdigitalconsentmap,
PARAM_RAW
);
$temp->add($setting);
$ADMIN->add('privacy', $temp);
// Policy settings.
$temp = new admin_settingpage('policysettings', new lang_string('policysettings', 'admin'));
$temp->add(new admin_settings_sitepolicy_handler_select('sitepolicyhandler', new lang_string('sitepolicyhandler', 'core_admin'),
new lang_string('sitepolicyhandler_desc', 'core_admin')));
$temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'core_admin'),
new lang_string('sitepolicy_help', 'core_admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'core_admin'),
new lang_string('sitepolicyguest_help', 'core_admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
$ADMIN->add('privacy', $temp);
}
@@ -0,0 +1,73 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_assignmentupgrade.
*
* @package tool_assignmentupgrade
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_assignmentupgrade\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\writer;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_assignmentupgrade implementing metadata, plugin, and user_preference providers.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\user_preference_provider {
/**
* Returns meta data about this system.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
$collection->add_user_preference(
'tool_assignmentupgrade_perpage',
'privacy:metadata:preference:perpage'
);
return $collection;
}
/**
* Export all user preferences for the plugin.
*
* @param int $userid The userid of the user whose data is to be exported.
*/
public static function export_user_preferences($userid) {
$perpage = get_user_preferences('tool_assignmentupgrade_perpage', null, $userid);
if ($perpage !== null) {
writer::export_user_preference(
'tool_assignmentupgrade',
'perpage',
$perpage,
get_string('privacy:metadata:preference:perpage', 'tool_assignmentupgrade')
);
}
}
}
@@ -58,3 +58,4 @@ $string['upgradeallconfirm'] = 'Upgrade all assignments?';
$string['upgradeprogress'] = 'Upgrade assignment {$a->current} of {$a->total}';
$string['upgradesingle'] = 'Upgrade single assignment';
$string['viewcourse'] = 'View the course with the converted assignment';
$string['privacy:metadata:preference:perpage'] = 'The assignment upgrade records per page preference set for the user.';
@@ -0,0 +1,75 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy tests for tool_assignmentupgrade.
*
* @package tool_assignmentupgrade
* @category test
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use \core_privacy\tests\provider_testcase;
use \core_privacy\local\request\writer;
use \tool_assignmentupgrade\privacy\provider;
/**
* Unit tests for tool_assignmentupgrade/classes/privacy/policy
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_assignmentupgrade_privacy_testcase extends provider_testcase {
/**
* Overriding setUp() function to always reset after tests.
*/
public function setUp() {
$this->resetAfterTest(true);
}
/**
* Test for provider::test_export_user_preferences().
*/
public function test_export_user_preferences() {
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
// Add a user home page preference for the User.
set_user_preference('tool_assignmentupgrade_perpage', '100', $user);
// Test the user preference exists.
$params = [
'userid' => $user->id,
'name' => 'tool_assignmentupgrade_perpage'
];
// Test the user preferences export contains 1 user preference record for the User.
provider::export_user_preferences($user->id);
$contextuser = context_user::instance($user->id);
$writer = writer::with_context($contextuser);
$this->assertTrue($writer->has_any_data());
$exportedpreferences = $writer->get_user_preferences('tool_assignmentupgrade');
$this->assertCount(1, (array) $exportedpreferences);
$this->assertEquals('100', $exportedpreferences->perpage->value);
}
}
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_availabilityconditions.
*
* @package tool_availabilityconditions
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_availabilityconditions\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_availabilityconditions implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -24,3 +24,4 @@
$string['manageplugins'] = 'Manage restrictions';
$string['pluginname'] = 'Availability condition management';
$string['privacy:metadata'] = 'The Availability condition management plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_behat.
*
* @package tool_behat
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_behat\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_behat implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
+1
View File
@@ -50,3 +50,4 @@ $string['wrongbehatsetup'] = 'Something is wrong with the behat setup and so ste
<li>$CFG->behat_dataroot, $CFG->behat_prefix and $CFG->behat_wwwroot are set in config.php with different values from $CFG->dataroot, $CFG->prefix and $CFG->wwwroot.</li>
<li>You ran "{$a->behatinit}" from your Moodle root directory.</li>
<li>Dependencies are installed in vendor/ and {$a->behatcommand} file has execution permissions.</li></ul>';
$string['privacy:metadata'] = 'The Acceptance testing plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_capability.
*
* @package tool_capability
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_capability\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_capability implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -34,3 +34,4 @@ $string['pluginname'] = 'Capability overview';
$string['reportforcapability'] = 'Report for capability \'{$a}\'';
$string['reportsettings'] = 'Report settings';
$string['roleslabel'] = 'Roles:';
$string['privacy:metadata'] = 'The Capability overview plugin does not store any personal data.';
+1 -1
View File
@@ -167,7 +167,7 @@ class api {
$params['roleid'] = $roleid;
$params['userid'] = $userid;
$sql = 'SELECT u.id AS userid, ra.id, ctx.id AS contextid
$sql = 'SELECT DISTINCT u.id AS userid, ra.id, ctx.id AS contextid
FROM {user} u
JOIN {cohort_members} cm ON u.id = cm.userid
JOIN {context} ctx ON u.id = ctx.instanceid AND ctx.contextlevel = :usercontext
@@ -98,7 +98,7 @@ class cohort_role_assignments_table extends table_sql {
);
$context = context_helper::instance_by_id($data->cohortcontextid);
$exporter = new \tool_lp\external\cohort_summary_exporter($record, array('context' => $context));
$exporter = new \core_cohort\external\cohort_summary_exporter($record, array('context' => $context));
$cohort = $exporter->export($OUTPUT);
$html = $OUTPUT->render_from_template('tool_cohortroles/cohort-in-list', $cohort);
@@ -0,0 +1,200 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_cohortroles.
*
* @package tool_cohortroles
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_cohortroles\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\context;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_cohortroles implementing metadata and plugin providers.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\plugin\provider {
/**
* Returns meta data about this system.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
// The tool_cohortroles plugin utilises the mdl_tool_cohortroles table.
$collection->add_database_table(
'tool_cohortroles',
[
'id' => 'privacy:metadata:tool_cohortroles:id',
'cohortid' => 'privacy:metadata:tool_cohortroles:cohortid',
'roleid' => 'privacy:metadata:tool_cohortroles:roleid',
'userid' => 'privacy:metadata:tool_cohortroles:userid',
'timecreated' => 'privacy:metadata:tool_cohortroles:timecreated',
'timemodified' => 'privacy:metadata:tool_cohortroles:timemodified',
'usermodified' => 'privacy:metadata:tool_cohortroles:usermodified'
],
'privacy:metadata:tool_cohortroles'
);
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid($userid) {
$contextlist = new contextlist();
// Retrieve the User context associated with tool_cohortroles records.
$sql = "SELECT DISTINCT c.id
FROM {context} c
JOIN {tool_cohortroles} cr ON cr.userid = c.instanceid AND c.contextlevel = :contextuser
WHERE cr.userid = :userid";
$params = [
'contextuser' => CONTEXT_USER,
'userid' => $userid
];
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
// If the user has tool_cohortroles data, then only the User context should be present so get the first context.
$contexts = $contextlist->get_contexts();
if (count($contexts) == 0) {
return;
}
$context = reset($contexts);
// Sanity check that context is at the User context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
// Retrieve the tool_cohortroles records created for the user.
$sql = 'SELECT cr.id as cohortroleid,
c.name as cohortname,
c.idnumber as cohortidnumber,
c.description as cohortdescription,
r.shortname as roleshortname,
cr.userid as userid,
cr.timecreated as timecreated,
cr.timemodified as timemodified
FROM {tool_cohortroles} cr
JOIN {cohort} c ON c.id = cr.cohortid
JOIN {role} r ON r.id = cr.roleid
WHERE cr.userid = :userid';
$params = [
'userid' => $userid
];
$cohortroles = $DB->get_records_sql($sql, $params);
foreach ($cohortroles as $cohortrole) {
// The tool_cohortroles data export is organised in:
// {User Context}/Cohort roles management/{cohort name}/{role shortname}/data.json.
$subcontext = [
get_string('pluginname', 'tool_cohortroles'),
$cohortrole->cohortname,
$cohortrole->roleshortname
];
$data = (object) [
'cohortname' => $cohortrole->cohortname,
'cohortidnumber' => $cohortrole->cohortidnumber,
'cohortdescription' => $cohortrole->cohortdescription,
'roleshortname' => $cohortrole->roleshortname,
'userid' => transform::user($cohortrole->userid),
'timecreated' => transform::datetime($cohortrole->timecreated),
'timemodified' => transform::datetime($cohortrole->timemodified)
];
writer::with_context($context)->export_data($subcontext, $data);
}
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
global $DB;
// Sanity check that context is at the User context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
// Delete the tool_cohortroles records created for the userid.
$DB->delete_records('tool_cohortroles', ['userid' => $userid]);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
// If the user has tool_cohortroles data, then only the User context should be present so get the first context.
$contexts = $contextlist->get_contexts();
if (count($contexts) == 0) {
return;
}
$context = reset($contexts);
// Sanity check that context is at the User context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
// Delete the tool_cohortroles records created for the userid.
$DB->delete_records('tool_cohortroles', ['userid' => $userid]);
}
}
@@ -42,3 +42,11 @@ $string['selectrole'] = 'Select role';
$string['selectusers'] = 'Select users to assign role';
$string['taskname'] = 'Sync cohort role assignments';
$string['thisuserroles'] = 'Roles assigned relative to this user';
$string['privacy:metadata:tool_cohortroles'] = 'The Cohort roles management plugin stores user cohort role mappings.';
$string['privacy:metadata:tool_cohortroles:id'] = 'The ID of the cohort role mapping record.';
$string['privacy:metadata:tool_cohortroles:cohortid'] = 'The ID of the cohort.';
$string['privacy:metadata:tool_cohortroles:roleid'] = 'The ID of the role.';
$string['privacy:metadata:tool_cohortroles:userid'] = 'The ID of the user.';
$string['privacy:metadata:tool_cohortroles:timecreated'] = 'The date/time of when the cohort role mapping was created.';
$string['privacy:metadata:tool_cohortroles:timemodified'] = 'The date/time of when the cohort role mapping was modified.';
$string['privacy:metadata:tool_cohortroles:usermodified'] = 'The ID of the user who last modified the cohort role mapping.';
@@ -0,0 +1,206 @@
<?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 tool_cohortroles implementation of the privacy API.
*
* @package tool_cohortroles
* @category test
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
use \core_privacy\local\request\writer;
use \core_privacy\local\request\approved_contextlist;
use \tool_cohortroles\api;
use \tool_cohortroles\privacy\provider;
/**
* Unit tests for the tool_cohortroles implementation of the privacy API.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_cohortroles_privacy_testcase extends \core_privacy\tests\provider_testcase {
/**
* Overriding setUp() function to always reset after tests.
*/
public function setUp() {
$this->resetAfterTest(true);
}
/**
* Test for provider::get_contexts_for_userid().
*/
public function test_get_contexts_for_userid() {
global $DB;
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$this->setAdminUser();
$nocohortroles = 3;
$this->setup_test_scenario_data($user->id, $nocohortroles);
// Test the User's assigned cohortroles matches 3.
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
$this->assertCount($nocohortroles, $cohortroles);
// Test the User's retrieved contextlist contains only one context.
$contextlist = provider::get_contexts_for_userid($user->id);
$contexts = $contextlist->get_contexts();
$this->assertCount(1, $contexts);
// Test the User's contexts equal the User's own context.
$context = reset($contexts);
$this->assertEquals(CONTEXT_USER, $context->contextlevel);
$this->assertEquals($user->id, $context->instanceid);
}
/**
* Test for provider::export_user_data().
*/
public function test_export_user_data() {
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$this->setAdminUser();
$nocohortroles = 3;
$this->setup_test_scenario_data($user->id, $nocohortroles);
// Test the User's retrieved contextlist contains only one context.
$contextlist = provider::get_contexts_for_userid($user->id);
$contexts = $contextlist->get_contexts();
$this->assertCount(1, $contexts);
// Test the User's contexts equal the User's own context.
$context = reset($contexts);
$this->assertEquals(CONTEXT_USER, $context->contextlevel);
$this->assertEquals($user->id, $context->instanceid);
// Retrieve the User's tool_cohortroles data.
$approvedcontextlist = new approved_contextlist($user, 'tool_cohortroles', $contextlist->get_contextids());
provider::export_user_data($approvedcontextlist);
// Test the tool_cohortroles data is exported at the User context level.
$writer = writer::with_context($context);
$this->assertTrue($writer->has_any_data());
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context() {
global $DB;
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$this->setAdminUser();
$nocohortroles = 4;
$this->setup_test_scenario_data($user->id, $nocohortroles);
// Test the User's assigned cohortroles matches 4.
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
$this->assertCount($nocohortroles, $cohortroles);
// Test the User's retrieved contextlist contains only one context.
$contextlist = provider::get_contexts_for_userid($user->id);
$contexts = $contextlist->get_contexts();
$this->assertCount(1, $contexts);
// Test the User's contexts equal the User's own context.
$context = reset($contexts);
$this->assertEquals(CONTEXT_USER, $context->contextlevel);
$this->assertEquals($user->id, $context->instanceid);
// Delete all the User's records in mdl_tool_cohortroles table by the specified User context.
provider::delete_data_for_all_users_in_context($context);
// Test the cohort roles records in mdl_tool_cohortroles table is equals zero.
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
$this->assertCount(0, $cohortroles);
}
/**
* Test for provider::delete_data_for_user().
*/
public function test_delete_data_for_user() {
global $DB;
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$this->setAdminUser();
$nocohortroles = 4;
$this->setup_test_scenario_data($user->id, $nocohortroles);
// Test the User's assigned cohortroles matches 4.
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
$this->assertCount($nocohortroles, $cohortroles);
// Test the User's retrieved contextlist contains only one context.
$contextlist = provider::get_contexts_for_userid($user->id);
$contexts = $contextlist->get_contexts();
$this->assertCount(1, $contexts);
// Test the User's contexts equal the User's own context.
$context = reset($contexts);
$this->assertEquals(CONTEXT_USER, $context->contextlevel);
$this->assertEquals($user->id, $context->instanceid);
// Delete all the User's records in mdl_tool_cohortroles table by the specified User approved context list.
$approvedcontextlist = new approved_contextlist($user, 'tool_cohortroles', $contextlist->get_contextids());
provider::delete_data_for_user($approvedcontextlist);
// Test the records in mdl_tool_cohortroles table is equals zero.
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
$this->assertCount(0, $cohortroles);
}
/**
* Helper function to setup tool_cohortroles records for testing a specific user.
*
* @param int $userid The ID of the user used for testing.
* @param int $nocohortroles The number of tool_cohortroles to create for the user.
* @throws \core_competency\invalid_persistent_exception
* @throws coding_exception
*/
protected function setup_test_scenario_data($userid, $nocohortroles) {
$roleid = create_role('Sausage Roll', 'sausageroll', 'mmmm');
for ($c = 0; $c < $nocohortroles; $c++) {
$cohort = $this->getDataGenerator()->create_cohort();
$params = (object)array(
'userid' => $userid,
'roleid' => $roleid,
'cohortid' => $cohort->id
);
api::create_cohort_role_assignment($params);
}
}
}
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_customlang.
*
* @package tool_customlang
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_customlang\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_customlang implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -59,3 +59,4 @@ $string['placeholderwarning'] = 'string contains a placeholder';
$string['pluginname'] = 'Language customisation';
$string['savecheckin'] = 'Save changes to the language pack';
$string['savecontinue'] = 'Apply changes and continue editing';
$string['privacy:metadata'] = 'The Language customisation plugin does not store any personal data.';
+5
View File
@@ -159,6 +159,11 @@ class tool_customlang_utils {
$needsupdate = true;
$current[$stringid]->local = $stringlocal;
$current[$stringid]->timecustomized = $now;
} else if (isset($currentlocal) && $stringlocal !== $currentlocal) {
// If local string has been removed, we need to remove also the old local value from DB.
$needsupdate = true;
$current[$stringid]->local = null;
$current[$stringid]->timecustomized = $now;
}
if ($needsupdate) {
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_dbtransfer.
*
* @package tool_dbtransfer
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_dbtransfer\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_dbtransfer implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -40,4 +40,4 @@ $string['transferdata'] = 'Transfer data';
$string['transferdbintro'] = 'This script will transfer the entire contents of this database to another database server. It is often used for migration of data to different database type.';
$string['transferdbtoserver'] = 'Transfer this Moodle database to another server';
$string['transferringdbto'] = 'Transferring this {$a->dbtypefrom} database to {$a->dbtype} database "{$a->dbname}" on "{$a->dbhost}"';
$string['privacy:metadata'] = 'The Database transfer plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_filetypes.
*
* @package tool_filetypes
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_filetypes\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_filetypes implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -67,3 +67,4 @@ $string['source_custom'] = 'Custom';
$string['source_deleted'] = 'Deleted';
$string['source_modified'] = 'Modified';
$string['source_standard'] = 'Standard';
$string['privacy:metadata'] = 'The File types plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_generator.
*
* @package tool_generator
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_generator\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_generator implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -122,3 +122,4 @@ $string['testplansize_4'] = 'XL ({$a->users} users, {$a->loops} loops and {$a->r
$string['testplansize_5'] = 'XXL ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
$string['updateuserspassword'] = 'Update course users password';
$string['updateuserspassword_help'] = 'JMeter needs to login as the course users, you can set the users password using $CFG->tool_generator_users_password in config.php; this setting updates the course user\'s password according to $CFG->tool_generator_users_password. It can be useful in case you are using a course not generated by tool_generator or $CFG->tool_generator_users_password was not set when you created the test courses.';
$string['privacy:metadata'] = 'The Development data generator plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_health.
*
* @package tool_health
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_health\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_health implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -29,3 +29,4 @@ $string['healthproblemsolution'] = 'Health problem solution';
$string['healthreturntomain'] = 'Continue';
$string['healthsolution'] = 'Solution';
$string['pluginname'] = 'Health center';
$string['privacy:metadata'] = 'The Health center plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_innodb.
*
* @package tool_innodb
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_innodb\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_innodb implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -24,3 +24,4 @@
*/
$string['pluginname'] = 'Convert to InnoDB';
$string['privacy:metadata'] = 'The Convert to InnoDB plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_installaddon.
*
* @package tool_installaddon
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_installaddon\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_installaddon implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -59,3 +59,4 @@ $string['remoterequestpluginfoexception'] = 'Oops... An error occurred while try
$string['remoterequestnoninstallable'] = 'There is a request to install plugin {$a->name} ({$a->component}) version {$a->version} from the Moodle plugins directory on this site. However, the plugin installation pre-check failed (reason code: {$a->reason}).';
$string['typedetectionfailed'] = 'Unable to detect the plugin type. Please choose the plugin type manually.';
$string['typedetectionmismatch'] = 'The selected plugin type does not match the one declared by the plugin: {$a}';
$string['privacy:metadata'] = 'The Plugin installer plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_langimport.
*
* @package tool_langimport
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_langimport\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_langimport implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -48,3 +48,4 @@ $string['selectlangs'] = 'Select languages to uninstall';
$string['uninstall'] = 'Uninstall selected language pack(s)';
$string['uninstallconfirm'] = 'You are about to completely uninstall these language packs: <strong>{$a}</strong>. Are you sure?';
$string['updatelangs'] = 'Update all installed language packs';
$string['privacy:metadata'] = 'The Language packs plugin does not store any personal data.';
@@ -0,0 +1,148 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy helper.
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_log\local\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\request\transform;
/**
* Privacy helper class.
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper {
/**
* Returns an event from a standard record.
*
* @see \logstore_standard\log\store::get_log_event()
* @param object $data Log data.
* @return \core\event\base
*/
protected static function restore_event_from_standard_record($data) {
$extra = ['origin' => $data->origin, 'ip' => $data->ip, 'realuserid' => $data->realuserid];
$data = (array) $data;
$id = $data['id'];
$data['other'] = unserialize($data['other']);
if ($data['other'] === false) {
$data['other'] = [];
}
unset($data['origin']);
unset($data['ip']);
unset($data['realuserid']);
unset($data['id']);
if (!$event = \core\event\base::restore($data, $extra)) {
return null;
}
return $event;
}
/**
* Transform a standard log record for a user.
*
* @param object $record The record.
* @param int $userid The user ID.
* @return array
*/
public static function transform_standard_log_record_for_userid($record, $userid) {
// Restore the event to try to get the name, description and other field.
$restoredevent = static::restore_event_from_standard_record($record);
if ($restoredevent) {
$name = $restoredevent->get_name();
$description = $restoredevent->get_description();
$other = $restoredevent->other;
} else {
$name = $record->eventname;
$description = "Unknown event ({$name})";
$other = unserialize($record->other);
}
$realuserid = $record->realuserid;
$isauthor = $record->userid == $userid;
$isrelated = $record->relateduserid == $userid;
$isrealuser = $realuserid == $userid;
$ismasqueraded = $realuserid !== null && $record->userid != $realuserid;
$ismasquerading = $isrealuser && !$isauthor;
$isanonymous = $record->anonymous;
$data = [
'name' => $name,
'description' => $description,
'timecreated' => transform::datetime($record->timecreated),
'ip' => $record->ip,
'origin' => static::transform_origin($record->origin),
'other' => $other ? $other : []
];
if ($isanonymous) {
$data['action_was_done_anonymously'] = transform::yesno($isanonymous);
}
if ($isauthor || !$isanonymous) {
$data['authorid'] = transform::user($record->userid);
$data['author_of_the_action_was_you'] = transform::yesno($isauthor);
}
if ($record->relateduserid) {
$data['relateduserid'] = transform::user($record->relateduserid);
$data['related_user_was_you'] = transform::yesno($isrelated);
}
if ($ismasqueraded) {
$data['author_of_the_action_was_masqueraded'] = transform::yesno(true);
if ($ismasquerading || !$isanonymous) {
$data['masqueradinguserid'] = transform::user($realuserid);
$data['masquerading_user_was_you'] = transform::yesno($ismasquerading);
}
}
return $data;
}
/**
* Transform origin.
*
* @param string $origin The page request origin.
* @return string
*/
public static function transform_origin($origin) {
switch ($origin) {
case 'cli':
case 'restore':
case 'web':
case 'ws':
return get_string('privacy:request:origin:' . $origin, 'tool_log');
break;
}
return $origin;
}
}
@@ -0,0 +1,78 @@
<?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/>.
/**
* Logstore provider interface.
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_log\local\privacy;
defined('MOODLE_INTERNAL') || die();
use context;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\approved_contextlist;
/**
* Logstore provider interface.
*
* Logstore subplugins providers must implement this interface.
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface logstore_provider extends \core_privacy\local\request\plugin\subplugin_provider {
/**
* Add contexts that contain user information for the specified user.
*
* @param contextlist $contextlist The contextlist to add the contexts to.
* @param int $userid The user to find the contexts for.
* @return void
*/
public static function add_contexts_for_userid(contextlist $contextlist, $userid);
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
* @return void
*/
public static function export_user_data(approved_contextlist $contextlist);
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
* @return void
*/
public static function delete_data_for_all_users_in_context(context $context);
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
* @return void
*/
public static function delete_data_for_user(approved_contextlist $contextlist);
}
@@ -0,0 +1,123 @@
<?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/>.
/**
* Moodle database: export and delete.
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_log\local\privacy;
defined('MOODLE_INTERNAL') || die();
use context;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\writer;
/**
* Moodle database: export and delete trait.
*
* This is to be used with logstores which use a database and table with the same columns
* as the core plugin 'logstore_standard'.
*
* This trait expects the following methods to be present in the object:
*
* - public static function get_database_and_table(): [moodle_database|null, string|null]
* - public static function get_export_subcontext(): []
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
trait moodle_database_export_and_delete {
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
list($db, $table) = static::get_database_and_table();
if (!$db || !$table) {
return;
}
$userid = $contextlist->get_user()->id;
list($insql, $inparams) = $db->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
$sql = "(userid = :userid1 OR relateduserid = :userid2 OR realuserid = :userid3) AND contextid $insql";
$params = array_merge($inparams, [
'userid1' => $userid,
'userid2' => $userid,
'userid3' => $userid,
]);
$path = static::get_export_subcontext();
$flush = function($lastcontextid, $data) use ($path) {
$context = context::instance_by_id($lastcontextid);
writer::with_context($context)->export_data($path, (object) ['logs' => $data]);
};
$lastcontextid = null;
$data = [];
$recordset = $db->get_recordset_select($table, $sql, $params, 'contextid, timecreated, id');
foreach ($recordset as $record) {
if ($lastcontextid && $lastcontextid != $record->contextid) {
$flush($lastcontextid, $data);
$data = [];
}
$data[] = helper::transform_standard_log_record_for_userid($record, $userid);
$lastcontextid = $record->contextid;
}
if ($lastcontextid) {
$flush($lastcontextid, $data);
}
$recordset->close();
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(context $context) {
list($db, $table) = static::get_database_and_table();
if (!$db || !$table) {
return;
}
$db->delete_records($table, ['contextid' => $context->id]);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
list($db, $table) = static::get_database_and_table();
if (!$db || !$table) {
return;
}
list($insql, $inparams) = $db->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
$params = array_merge($inparams, ['userid' => $contextlist->get_user()->id]);
$db->delete_records_select($table, "userid = :userid AND contextid $insql", $params);
}
}
+110
View File
@@ -0,0 +1,110 @@
<?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/>.
/**
* Data provider.
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_log\privacy;
defined('MOODLE_INTERNAL') || die();
use context;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use tool_log\log\manager;
/**
* Data provider class.
*
* @package tool_log
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\subsystem\provider {
/**
* Returns metadata.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
$collection->add_plugintype_link('logstore', [], 'privacy:metadata:logstore');
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid($userid) {
$contextlist = new \core_privacy\local\request\contextlist();
static::call_subplugins_method_with_args('add_contexts_for_userid', [$contextlist, $userid]);
return $contextlist;
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
static::call_subplugins_method_with_args('export_user_data', [$contextlist]);
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(context $context) {
static::call_subplugins_method_with_args('delete_data_for_all_users_in_context', [$context]);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
static::call_subplugins_method_with_args('delete_data_for_user', [$contextlist]);
}
/**
* Invoke the subplugins method with arguments.
*
* @param string $method The method name.
* @param array $args The arguments.
* @return void
*/
protected static function call_subplugins_method_with_args($method, array $args = []) {
$interface = \tool_log\local\privacy\logstore_provider::class;
\core_privacy\manager::plugintype_class_callback('logstore', $interface, $method, $args);
}
}
+7 -1
View File
@@ -26,7 +26,13 @@ $string['actlogshdr'] = 'Available log stores';
$string['configlogplugins'] = 'Please enable all required plugins and arrange them in appropriate order.';
$string['logging'] = 'Logging';
$string['managelogging'] = 'Manage log stores';
$string['reportssupported'] = 'Reports supported';
$string['pluginname'] = 'Log store manager';
$string['privacy:metadata:logstore'] = 'The log stores';
$string['privacy:path:logs'] = 'Logs';
$string['privacy:request:origin:cli'] = 'Command line tool';
$string['privacy:request:origin:restore'] = 'Backup being restored';
$string['privacy:request:origin:web'] = 'Standard web request';
$string['privacy:request:origin:ws'] = 'Mobile app or web service';
$string['reportssupported'] = 'Reports supported';
$string['subplugintype_logstore'] = 'Log store';
$string['subplugintype_logstore_plural'] = 'Log stores';
@@ -0,0 +1,114 @@
<?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/>.
/**
* Data provider.
*
* @package logstore_database
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace logstore_database\privacy;
defined('MOODLE_INTERNAL') || die();
use context;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\contextlist;
/**
* Data provider class.
*
* @package logstore_database
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\tool_log\local\privacy\logstore_provider {
use \tool_log\local\privacy\moodle_database_export_and_delete;
/**
* Returns metadata.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
$collection->add_external_location_link('log', [
'eventname' => 'privacy:metadata:log:eventname',
'userid' => 'privacy:metadata:log:userid',
'relateduserid' => 'privacy:metadata:log:relateduserid',
'anonymous' => 'privacy:metadata:log:anonymous',
'other' => 'privacy:metadata:log:other',
'timecreated' => 'privacy:metadata:log:timecreated',
'origin' => 'privacy:metadata:log:origin',
'ip' => 'privacy:metadata:log:ip',
'realuserid' => 'privacy:metadata:log:realuserid',
], 'privacy:metadata:log');
return $collection;
}
/**
* Add contexts that contain user information for the specified user.
*
* @param contextlist $contextlist The contextlist to add the contexts to.
* @param int $userid The user to find the contexts for.
* @return void
*/
public static function add_contexts_for_userid(contextlist $contextlist, $userid) {
list($db, $table) = static::get_database_and_table();
if (!$db || !$table) {
return;
}
$sql = 'userid = :userid1 OR relateduserid = :userid2 OR realuserid = :userid3';
$params = ['userid1' => $userid, 'userid2' => $userid, 'userid3' => $userid];
$contextids = $db->get_fieldset_select($table, 'DISTINCT contextid', $sql, $params);
if (empty($contextids)) {
return;
}
$sql = implode(' UNION ', array_map(function($id) use ($db) {
return 'SELECT ' . $id . $db->sql_null_from_clause();
}, $contextids));
$contextlist->add_from_sql($sql, []);
}
/**
* Get the database object.
*
* @return array Containing moodle_database, string, or null values.
*/
protected static function get_database_and_table() {
$manager = get_log_manager();
$store = new \logstore_database\log\store($manager);
$db = $store->get_extdb();
return $db ? [$db, $store->get_config_value('dbtable')] : [null, null];
}
/**
* Get the path to export the logs to.
*
* @return array
*/
protected static function get_export_subcontext() {
return [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_database')];
}
}
@@ -44,6 +44,16 @@ $string['other'] = 'Other';
$string['participating'] = 'Participating';
$string['pluginname'] = 'External database log';
$string['pluginname_desc'] = 'A log plugin that stores log entries in an external database table.';
$string['privacy:metadata:log'] = 'A collection of past events';
$string['privacy:metadata:log:anonymous'] = 'Whether the event was flagged as anonymous';
$string['privacy:metadata:log:eventname'] = 'The event name';
$string['privacy:metadata:log:ip'] = 'The IP address used at the time of the event';
$string['privacy:metadata:log:origin'] = 'The origin of the event';
$string['privacy:metadata:log:other'] = 'Additional information about the event';
$string['privacy:metadata:log:realuserid'] = 'The ID of the real user behind the event, when masquerading a user.';
$string['privacy:metadata:log:relateduserid'] = 'The ID of a user related to this event';
$string['privacy:metadata:log:timecreated'] = 'The time at which the event occurred';
$string['privacy:metadata:log:userid'] = 'The ID of the user who triggered this event';
$string['read'] = 'Read';
$string['tablenotfound'] = 'Specified table was not found';
$string['teaching'] = 'Teaching';
@@ -0,0 +1,416 @@
<?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/>.
/**
* Data provider tests.
*
* @package logstore_database
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use logstore_database\privacy\provider;
require_once(__DIR__ . '/fixtures/event.php');
/**
* Data provider testcase class.
*
* This testcase is almost identical to the logstore_standard testcase, aside from the
* initialisation of the relevant logstore obviously.
*
* @package logstore_database
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class logstore_database_privacy_testcase extends provider_testcase {
public function setUp() {
global $CFG;
$this->resetAfterTest();
$this->preventResetByRollback(); // Logging waits till the transaction gets committed.
// Fake the settings, we will abuse the standard plugin table here...
set_config('dbdriver', $CFG->dblibrary . '/' . $CFG->dbtype, 'logstore_database');
set_config('dbhost', $CFG->dbhost, 'logstore_database');
set_config('dbuser', $CFG->dbuser, 'logstore_database');
set_config('dbpass', $CFG->dbpass, 'logstore_database');
set_config('dbname', $CFG->dbname, 'logstore_database');
set_config('dbtable', $CFG->prefix . 'logstore_standard_log', 'logstore_database');
if (!empty($CFG->dboptions['dbpersist'])) {
set_config('dbpersist', 1, 'logstore_database');
} else {
set_config('dbpersist', 0, 'logstore_database');
}
if (!empty($CFG->dboptions['dbsocket'])) {
set_config('dbsocket', $CFG->dboptions['dbsocket'], 'logstore_database');
} else {
set_config('dbsocket', '', 'logstore_database');
}
if (!empty($CFG->dboptions['dbport'])) {
set_config('dbport', $CFG->dboptions['dbport'], 'logstore_database');
} else {
set_config('dbport', '', 'logstore_database');
}
if (!empty($CFG->dboptions['dbschema'])) {
set_config('dbschema', $CFG->dboptions['dbschema'], 'logstore_database');
} else {
set_config('dbschema', '', 'logstore_database');
}
if (!empty($CFG->dboptions['dbcollation'])) {
set_config('dbcollation', $CFG->dboptions['dbcollation'], 'logstore_database');
} else {
set_config('dbcollation', '', 'logstore_database');
}
if (!empty($CFG->dboptions['dbhandlesoptions'])) {
set_config('dbhandlesoptions', $CFG->dboptions['dbhandlesoptions'], 'logstore_database');
} else {
set_config('dbhandlesoptions', false, 'logstore_database');
}
}
public function test_get_contexts_for_userid() {
$admin = \core_user::get_user(2);
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$c2 = $this->getDataGenerator()->create_course();
$cm2 = $this->getDataGenerator()->create_module('url', ['course' => $c2]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$cm1ctx = context_module::instance($cm1->cmid);
$cm2ctx = context_module::instance($cm2->cmid);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), []);
$e = \logstore_database\event\unittest_executed::create(['context' => $cm1ctx]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]);
// User 2 is the related user.
$this->setUser(0);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u2), []);
$e = \logstore_database\event\unittest_executed::create(['context' => $cm2ctx, 'relateduserid' => $u2->id]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u2), [$cm2ctx]);
// Admin user is the real user.
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), []);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), []);
$this->setAdminUser();
\core\session\manager::loginas($u3->id, $sysctx);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx]);
// By admin user masquerading u1 related to u3.
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx]);
$this->setAdminUser();
\core\session\manager::loginas($u1->id, context_system::instance());
$e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u3->id]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$sysctx, $cm1ctx, $c2ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx, $c2ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx, $c2ctx]);
}
public function test_delete_data_for_user() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c2 = $this->getDataGenerator()->create_course();
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// Confirm data present.
$this->assertTrue($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
$this->assertEquals(3, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
// Delete all the things!
provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_database', [$c1ctx->id]));
$this->assertFalse($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
}
public function test_delete_data_for_all_users_in_context() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c2 = $this->getDataGenerator()->create_course();
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// Confirm data present.
$this->assertTrue($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
$this->assertEquals(3, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
// Delete all the things!
provider::delete_data_for_all_users_in_context($c1ctx);
$this->assertFalse($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
}
public function test_export_data_for_user() {
$admin = \core_user::get_user(2);
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$u4 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$c2 = $this->getDataGenerator()->create_course();
$cm2 = $this->getDataGenerator()->create_module('url', ['course' => $c2]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$cm1ctx = context_module::instance($cm1->cmid);
$cm2ctx = context_module::instance($cm2->cmid);
$path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_database')];
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx, 'other' => ['i' => 0]]);
$e->trigger();
// User 2 is related.
$this->setUser(0);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx, 'relateduserid' => $u2->id,
'other' => ['i' => 1]]);
$e->trigger();
// Admin user masquerades u3, which is related to u4.
$this->setAdminUser();
\core\session\manager::loginas($u3->id, $sysctx);
$e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx, 'relateduserid' => $u4->id,
'other' => ['i' => 2]]);
$e->trigger();
// Confirm data present for u1.
provider::export_user_data(new approved_contextlist($u1, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
$this->assertSame(0, $data->logs[0]['other']['i']);
// Confirm data present for u2.
writer::reset();
provider::export_user_data(new approved_contextlist($u2, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(false), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
$this->assertSame(1, $data->logs[0]['other']['i']);
// Confirm data present for u3.
writer::reset();
provider::export_user_data(new approved_contextlist($u3, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(false), $data->logs[0]['related_user_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertEquals(transform::yesno(false), $data->logs[0]['masquerading_user_was_you']);
$this->assertSame(2, $data->logs[0]['other']['i']);
// Confirm data present for u4.
writer::reset();
provider::export_user_data(new approved_contextlist($u4, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(false), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertEquals(transform::yesno(false), $data->logs[0]['masquerading_user_was_you']);
$this->assertSame(2, $data->logs[0]['other']['i']);
// Add anonymous events.
$this->setUser($u1);
$e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u2->id,
'anonymous' => true]);
$e->trigger();
$this->setAdminUser();
\core\session\manager::loginas($u3->id, $sysctx);
$e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u4->id,
'anonymous' => true]);
$e->trigger();
// Confirm data present for u1.
provider::export_user_data(new approved_contextlist($u1, 'logstore_database', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
// Confirm data present for u2.
writer::reset();
provider::export_user_data(new approved_contextlist($u2, 'logstore_database', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertArrayNotHasKey('author_of_the_action_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('authorid', $data->logs[0]);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
// Confirm data present for u3.
writer::reset();
provider::export_user_data(new approved_contextlist($u3, 'logstore_database', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertArrayNotHasKey('masquerading_user_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('masqueradinguserid', $data->logs[0]);
// Confirm data present for u4.
writer::reset();
provider::export_user_data(new approved_contextlist($u4, 'logstore_database', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertArrayNotHasKey('author_of_the_action_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('authorid', $data->logs[0]);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertArrayNotHasKey('masquerading_user_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('masqueradinguserid', $data->logs[0]);
}
/**
* Assert the content of a context list.
*
* @param contextlist $contextlist The collection.
* @param array $expected List of expected contexts or IDs.
* @return void
*/
protected function assert_contextlist_equals($contextlist, array $expected) {
$expectedids = array_map(function($context) {
if (is_object($context)) {
return $context->id;
}
return $context;
}, $expected);
$contextids = array_map('intval', $contextlist->get_contextids());
sort($contextids);
sort($expectedids);
$this->assertEquals($expectedids, $contextids);
}
/**
* Enable logging.
*
* @return void
*/
protected function enable_logging() {
set_config('enabled_stores', 'logstore_database', 'tool_log');
set_config('buffersize', 0, 'logstore_database');
set_config('logguests', 1, 'logstore_database');
get_log_manager(true);
}
/**
* Get the contextlist for a user.
*
* @param object $user The user.
* @return contextlist
*/
protected function get_contextlist_for_user($user) {
$contextlist = new contextlist();
provider::add_contexts_for_userid($contextlist, $user->id);
return $contextlist;
}
}
@@ -0,0 +1,220 @@
<?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/>.
/**
* Data provider.
*
* @package logstore_legacy
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace logstore_legacy\privacy;
defined('MOODLE_INTERNAL') || die();
use context;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use tool_log\local\privacy\helper;
/**
* Data provider class.
*
* @package logstore_legacy
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\tool_log\local\privacy\logstore_provider {
/**
* Returns metadata.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
$collection->add_external_location_link('log', [
'time' => 'privacy:metadata:log:time',
'userid' => 'privacy:metadata:log:userid',
'ip' => 'privacy:metadata:log:ip',
'action' => 'privacy:metadata:log:action',
'url' => 'privacy:metadata:log:url',
'info' => 'privacy:metadata:log:info',
], 'privacy:metadata:log');
return $collection;
}
/**
* Add contexts that contain user information for the specified user.
*
* @param contextlist $contextlist The contextlist to add the contexts to.
* @param int $userid The user to find the contexts for.
* @return void
*/
public static function add_contexts_for_userid(contextlist $contextlist, $userid) {
$sql = "
SELECT ctx.id
FROM {context} ctx
JOIN {log} l
ON (l.cmid = 0 AND l.course = ctx.instanceid AND ctx.contextlevel = :courselevel)
OR (l.cmid > 0 AND l.cmid = ctx.instanceid AND ctx.contextlevel = :modulelevel)
OR (l.course <= 0 AND ctx.id = :syscontextid)
WHERE l.userid = :userid";
$params = [
'courselevel' => CONTEXT_COURSE,
'modulelevel' => CONTEXT_MODULE,
'syscontextid' => SYSCONTEXTID,
'userid' => $userid,
];
$contextlist->add_from_sql($sql, $params);
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
$userid = $contextlist->get_user()->id;
list($insql, $inparams) = static::get_sql_where_from_contexts($contextlist->get_contexts());
if (empty($insql)) {
return;
}
$sql = "userid = :userid AND $insql";
$params = array_merge($inparams, ['userid' => $userid]);
$path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_legacy')];
$flush = function($lastcontextid, $data) use ($path) {
$context = context::instance_by_id($lastcontextid);
writer::with_context($context)->export_data($path, (object) ['logs' => $data]);
};
$lastcontextid = null;
$data = [];
$recordset = $DB->get_recordset_select('log', $sql, $params, 'course, cmid, time, id');
foreach ($recordset as $record) {
$event = \logstore_legacy\event\legacy_logged::restore_legacy($record);
$context = $event->get_context();
if ($lastcontextid && $lastcontextid != $context->id) {
$flush($lastcontextid, $data);
$data = [];
}
$extra = $event->get_logextra();
$data[] = [
'name' => $event->get_name(),
'description' => $event->get_description(),
'timecreated' => transform::datetime($event->timecreated),
'ip' => $extra['ip'],
'origin' => helper::transform_origin($extra['origin']),
];
$lastcontextid = $context->id;
}
if ($lastcontextid) {
$flush($lastcontextid, $data);
}
$recordset->close();
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(context $context) {
global $DB;
list($sql, $params) = static::get_sql_where_from_contexts([$context]);
if (empty($sql)) {
return;
}
$DB->delete_records_select('log', $sql, $params);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
list($sql, $params) = static::get_sql_where_from_contexts($contextlist->get_contexts());
if (empty($sql)) {
return;
}
$userid = $contextlist->get_user()->id;
$DB->delete_records_select('log', "$sql AND userid = :userid", array_merge($params, ['userid' => $userid]));
}
/**
* Get an SQL where statement from a list of contexts.
*
* @param array $contexts The contexts.
* @return array [$sql, $params]
*/
protected static function get_sql_where_from_contexts(array $contexts) {
global $DB;
$sorted = array_reduce($contexts, function ($carry, $context) {
$level = $context->contextlevel;
if ($level == CONTEXT_MODULE || $level == CONTEXT_COURSE) {
$carry[$level][] = $context->instanceid;
} else if ($level == CONTEXT_SYSTEM) {
$carry[$level] = $context->id;
}
return $carry;
}, [
CONTEXT_COURSE => [],
CONTEXT_MODULE => [],
CONTEXT_SYSTEM => null,
]);
$sqls = [];
$params = [];
if (!empty($sorted[CONTEXT_MODULE])) {
list($insql, $inparams) = $DB->get_in_or_equal($sorted[CONTEXT_MODULE], SQL_PARAMS_NAMED);
$sqls[] = "cmid $insql";
$params = array_merge($params, $inparams);
}
if (!empty($sorted[CONTEXT_COURSE])) {
list($insql, $inparams) = $DB->get_in_or_equal($sorted[CONTEXT_COURSE], SQL_PARAMS_NAMED);
$sqls[] = "cmid = 0 AND course $insql";
$params = array_merge($params, $inparams);
}
if (!empty($sorted[CONTEXT_SYSTEM])) {
$sqls[] = "course <= 0";
}
if (empty($sqls)) {
return [null, null];
}
return ['((' . implode(') OR (', $sqls) . '))', $params];
}
}
@@ -27,4 +27,11 @@ $string['loglegacy'] = 'Log legacy data';
$string['loglegacy_help'] = 'This plugin records log data to the legacy log table (mdl_log). This functionality has been replaced by newer, richer and more efficient logging plugins, so you should only run this plugin if you have old custom reports that directly query the old log table. Writing to the legacy logs will increase load, so it is recommended that you disable this plugin for performance reasons when it is not needed.';
$string['pluginname'] = 'Legacy log';
$string['pluginname_desc'] = 'A log plugin that stores log entries in the legacy log table.';
$string['privacy:metadata:log'] = 'A collection of past events';
$string['privacy:metadata:log:action'] = 'A description of the action';
$string['privacy:metadata:log:info'] = 'Additional information';
$string['privacy:metadata:log:ip'] = 'The IP address used at the time of the event';
$string['privacy:metadata:log:time'] = 'The date at wich the action took place';
$string['privacy:metadata:log:url'] = 'The URL related to the event';
$string['privacy:metadata:log:userid'] = 'The ID of the user who performed the action';
$string['taskcleanup'] = 'Legacy log table cleanup';
@@ -0,0 +1,344 @@
<?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/>.
/**
* Data provider tests.
*
* @package logstore_legacy
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use logstore_legacy\privacy\provider;
use logstore_legacy\event\unittest_executed;
require_once(__DIR__ . '/fixtures/event.php');
/**
* Data provider testcase class.
*
* @package logstore_legacy
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class logstore_legacy_privacy_testcase extends provider_testcase {
public function setUp() {
$this->resetAfterTest();
}
public function test_get_contexts_for_userid() {
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$cm1ctx = context_module::instance($cm1->cmid);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), []);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]);
// User 2 is the author.
$this->setUser($u2);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u2), []);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u2), [$cm1ctx]);
// User 3 is the author.
$this->setUser($u3);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), []);
$e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 3]]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx]);
}
public function test_delete_data_for_user() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c2 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$cm1ctx = context_module::instance($cm1->cmid);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]);
$e->trigger();
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]);
$e->trigger();
$e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 3]]);
$e->trigger();
$e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 4]]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 5]]);
$e->trigger();
$e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 6]]);
$e->trigger();
$e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 7]]);
$e->trigger();
// Assert what we have.
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0]));
$this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id]));
// Delete other context.
provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$c2ctx->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0]));
$this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id]));
// Delete system.
provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$sysctx->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id]));
// Delete course.
provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$c1ctx->id]));
$this->assertTrue($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0]));
$this->assertEquals(2, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id]));
// Delete course.
provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_legacy', [$cm1ctx->id]));
$this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['userid' => $u1->id, 'cmid' => 0, 'course' => 0]));
$this->assertEquals(0, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id]));
}
public function test_delete_data_for_all_users_in_context() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c2 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$cm1ctx = context_module::instance($cm1->cmid);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]);
$e->trigger();
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]);
$e->trigger();
$e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 3]]);
$e->trigger();
$e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 4]]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 5]]);
$e->trigger();
$e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 6]]);
$e->trigger();
$e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 7]]);
$e->trigger();
// Assert what we have.
$this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => 0]));
$this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id]));
// Delete other context.
provider::delete_data_for_all_users_in_context($c2ctx);
$this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => 0]));
$this->assertEquals(4, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u2->id]));
// Delete system.
provider::delete_data_for_all_users_in_context($sysctx);
$this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertTrue($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => 0]));
$this->assertEquals(3, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(2, $DB->count_records('log', ['userid' => $u2->id]));
// Delete course.
provider::delete_data_for_all_users_in_context($c1ctx);
$this->assertTrue($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => 0]));
$this->assertEquals(2, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(1, $DB->count_records('log', ['userid' => $u2->id]));
// Delete course.
provider::delete_data_for_all_users_in_context($cm1ctx);
$this->assertFalse($DB->record_exists('log', ['cmid' => $cm1->cmid, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => $c1->id]));
$this->assertFalse($DB->record_exists('log', ['cmid' => 0, 'course' => 0]));
$this->assertEquals(0, $DB->count_records('log', ['userid' => $u1->id]));
$this->assertEquals(0, $DB->count_records('log', ['userid' => $u2->id]));
}
public function test_export_data_for_user() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c2 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$cm1ctx = context_module::instance($cm1->cmid);
$this->enable_logging();
$manager = get_log_manager(true);
$path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_legacy')];
// User 1 is the author.
$this->setUser($u1);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 1]]);
$e->trigger();
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 2]]);
$e->trigger();
$e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 3]]);
$e->trigger();
$e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 4]]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 5]]);
$e->trigger();
$e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 6]]);
$e->trigger();
$e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 7]]);
$e->trigger();
// Test export.
provider::export_user_data(new approved_contextlist($u1, 'logstore_legacy', [$cm1ctx->id]));
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($cm1ctx)->get_data($path);
$this->assertCount(2, $data->logs);
writer::reset();
provider::export_user_data(new approved_contextlist($u1, 'logstore_legacy', [$c1ctx->id]));
$data = writer::with_context($cm1ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
writer::reset();
provider::export_user_data(new approved_contextlist($u1, 'logstore_legacy', [$sysctx->id]));
$data = writer::with_context($sysctx)->get_data($path);
$this->assertCount(1, $data->logs);
}
/**
* Assert the content of a context list.
*
* @param contextlist $contextlist The collection.
* @param array $expected List of expected contexts or IDs.
* @return void
*/
protected function assert_contextlist_equals($contextlist, array $expected) {
$expectedids = array_map(function($context) {
if (is_object($context)) {
return $context->id;
}
return $context;
}, $expected);
$contextids = array_map('intval', $contextlist->get_contextids());
sort($contextids);
sort($expectedids);
$this->assertEquals($expectedids, $contextids);
}
/**
* Enable logging.
*
* @return void
*/
protected function enable_logging() {
set_config('enabled_stores', 'logstore_legacy', 'tool_log');
set_config('loglegacy', 1, 'logstore_legacy');
get_log_manager(true);
}
/**
* Get the contextlist for a user.
*
* @param object $user The user.
* @return contextlist
*/
protected function get_contextlist_for_user($user) {
$contextlist = new contextlist();
provider::add_contexts_for_userid($contextlist, $user->id);
return $contextlist;
}
}
@@ -0,0 +1,107 @@
<?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/>.
/**
* Data provider.
*
* @package logstore_standard
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace logstore_standard\privacy;
defined('MOODLE_INTERNAL') || die();
use context;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\contextlist;
/**
* Data provider class.
*
* @package logstore_standard
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\tool_log\local\privacy\logstore_provider {
use \tool_log\local\privacy\moodle_database_export_and_delete;
/**
* Returns metadata.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
$collection->add_database_table('logstore_standard_log', [
'eventname' => 'privacy:metadata:log:eventname',
'userid' => 'privacy:metadata:log:userid',
'relateduserid' => 'privacy:metadata:log:relateduserid',
'anonymous' => 'privacy:metadata:log:anonymous',
'other' => 'privacy:metadata:log:other',
'timecreated' => 'privacy:metadata:log:timecreated',
'origin' => 'privacy:metadata:log:origin',
'ip' => 'privacy:metadata:log:ip',
'realuserid' => 'privacy:metadata:log:realuserid',
], 'privacy:metadata:log');
return $collection;
}
/**
* Add contexts that contain user information for the specified user.
*
* @param contextlist $contextlist The contextlist to add the contexts to.
* @param int $userid The user to find the contexts for.
* @return void
*/
public static function add_contexts_for_userid(contextlist $contextlist, $userid) {
$sql = "
SELECT l.contextid
FROM {logstore_standard_log} l
WHERE l.userid = :userid1
OR l.relateduserid = :userid2
OR l.realuserid = :userid3";
$contextlist->add_from_sql($sql, [
'userid1' => $userid,
'userid2' => $userid,
'userid3' => $userid,
]);
}
/**
* Get the database object.
*
* @return array Containing moodle_database, string, or null values.
*/
protected static function get_database_and_table() {
global $DB;
return [$DB, 'logstore_standard_log'];
}
/**
* Get the path to export the logs to.
*
* @return array
*/
protected static function get_export_subcontext() {
return [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_standard')];
}
}
@@ -25,4 +25,14 @@
$string['buffersize'] = 'Write buffer size';
$string['pluginname'] = 'Standard log';
$string['pluginname_desc'] = 'A log plugin stores log entries in a Moodle database table.';
$string['privacy:metadata:log'] = 'A collection of past events';
$string['privacy:metadata:log:anonymous'] = 'Whether the event was flagged as anonymous';
$string['privacy:metadata:log:eventname'] = 'The event name';
$string['privacy:metadata:log:ip'] = 'The IP address used at the time of the event';
$string['privacy:metadata:log:origin'] = 'The origin of the event';
$string['privacy:metadata:log:other'] = 'Additional information about the event';
$string['privacy:metadata:log:realuserid'] = 'The ID of the real user behind the event, when masquerading a user.';
$string['privacy:metadata:log:relateduserid'] = 'The ID of a user related to this event';
$string['privacy:metadata:log:timecreated'] = 'The time at which the event occurred';
$string['privacy:metadata:log:userid'] = 'The ID of the user who triggered this event';
$string['taskcleanup'] = 'Log table cleanup';
@@ -0,0 +1,373 @@
<?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/>.
/**
* Data provider tests.
*
* @package logstore_standard
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use logstore_standard\privacy\provider;
require_once(__DIR__ . '/fixtures/event.php');
/**
* Data provider testcase class.
*
* @package logstore_standard
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class logstore_standard_privacy_testcase extends provider_testcase {
public function setUp() {
$this->resetAfterTest();
$this->preventResetByRollback(); // Logging waits till the transaction gets committed.
}
public function test_get_contexts_for_userid() {
$admin = \core_user::get_user(2);
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$c2 = $this->getDataGenerator()->create_course();
$cm2 = $this->getDataGenerator()->create_module('url', ['course' => $c2]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$cm1ctx = context_module::instance($cm1->cmid);
$cm2ctx = context_module::instance($cm2->cmid);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), []);
$e = \logstore_standard\event\unittest_executed::create(['context' => $cm1ctx]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]);
// User 2 is the related user.
$this->setUser(0);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u2), []);
$e = \logstore_standard\event\unittest_executed::create(['context' => $cm2ctx, 'relateduserid' => $u2->id]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u2), [$cm2ctx]);
// Admin user is the real user.
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), []);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), []);
$this->setAdminUser();
\core\session\manager::loginas($u3->id, $sysctx);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx]);
// By admin user masquerading u1 related to u3.
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx]);
$this->setAdminUser();
\core\session\manager::loginas($u1->id, context_system::instance());
$e = \logstore_standard\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u3->id]);
$e->trigger();
$this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$sysctx, $cm1ctx, $c2ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx, $c2ctx]);
$this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx, $c2ctx]);
}
public function test_delete_data_for_user() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c2 = $this->getDataGenerator()->create_course();
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// Confirm data present.
$this->assertTrue($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
$this->assertEquals(3, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
// Delete all the things!
provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_standard', [$c1ctx->id]));
$this->assertFalse($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
}
public function test_delete_data_for_all_users_in_context() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c2 = $this->getDataGenerator()->create_course();
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c2ctx]);
$e->trigger();
// Confirm data present.
$this->assertTrue($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
$this->assertEquals(3, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
// Delete all the things!
provider::delete_data_for_all_users_in_context($c1ctx);
$this->assertFalse($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
}
public function test_export_data_for_user() {
$admin = \core_user::get_user(2);
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$u3 = $this->getDataGenerator()->create_user();
$u4 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
$c2 = $this->getDataGenerator()->create_course();
$cm2 = $this->getDataGenerator()->create_module('url', ['course' => $c2]);
$sysctx = context_system::instance();
$c1ctx = context_course::instance($c1->id);
$c2ctx = context_course::instance($c2->id);
$cm1ctx = context_module::instance($cm1->cmid);
$cm2ctx = context_module::instance($cm2->cmid);
$path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_standard')];
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx, 'other' => ['i' => 0]]);
$e->trigger();
// User 2 is related.
$this->setUser(0);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx, 'relateduserid' => $u2->id,
'other' => ['i' => 1]]);
$e->trigger();
// Admin user masquerades u3, which is related to u4.
$this->setAdminUser();
\core\session\manager::loginas($u3->id, $sysctx);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx, 'relateduserid' => $u4->id,
'other' => ['i' => 2]]);
$e->trigger();
// Confirm data present for u1.
provider::export_user_data(new approved_contextlist($u1, 'logstore_standard', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
$this->assertSame(0, $data->logs[0]['other']['i']);
// Confirm data present for u2.
writer::reset();
provider::export_user_data(new approved_contextlist($u2, 'logstore_standard', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(false), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
$this->assertSame(1, $data->logs[0]['other']['i']);
// Confirm data present for u3.
writer::reset();
provider::export_user_data(new approved_contextlist($u3, 'logstore_standard', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(false), $data->logs[0]['related_user_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertEquals(transform::yesno(false), $data->logs[0]['masquerading_user_was_you']);
$this->assertSame(2, $data->logs[0]['other']['i']);
// Confirm data present for u4.
writer::reset();
provider::export_user_data(new approved_contextlist($u4, 'logstore_standard', [$c2ctx->id, $c1ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertEmpty($data);
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(false), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertEquals(transform::yesno(false), $data->logs[0]['masquerading_user_was_you']);
$this->assertSame(2, $data->logs[0]['other']['i']);
// Add anonymous events.
$this->setUser($u1);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u2->id,
'anonymous' => true]);
$e->trigger();
$this->setAdminUser();
\core\session\manager::loginas($u3->id, $sysctx);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u4->id,
'anonymous' => true]);
$e->trigger();
// Confirm data present for u1.
provider::export_user_data(new approved_contextlist($u1, 'logstore_standard', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
// Confirm data present for u2.
writer::reset();
provider::export_user_data(new approved_contextlist($u2, 'logstore_standard', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertArrayNotHasKey('author_of_the_action_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('authorid', $data->logs[0]);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
// Confirm data present for u3.
writer::reset();
provider::export_user_data(new approved_contextlist($u3, 'logstore_standard', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertArrayNotHasKey('masquerading_user_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('masqueradinguserid', $data->logs[0]);
// Confirm data present for u4.
writer::reset();
provider::export_user_data(new approved_contextlist($u4, 'logstore_standard', [$c2ctx->id]));
$data = writer::with_context($c2ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
$this->assertArrayNotHasKey('author_of_the_action_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('authorid', $data->logs[0]);
$this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
$this->assertArrayNotHasKey('masquerading_user_was_you', $data->logs[0]);
$this->assertArrayNotHasKey('masqueradinguserid', $data->logs[0]);
}
/**
* Assert the content of a context list.
*
* @param contextlist $contextlist The collection.
* @param array $expected List of expected contexts or IDs.
* @return void
*/
protected function assert_contextlist_equals($contextlist, array $expected) {
$expectedids = array_map(function($context) {
if (is_object($context)) {
return $context->id;
}
return $context;
}, $expected);
$contextids = array_map('intval', $contextlist->get_contextids());
sort($contextids);
sort($expectedids);
$this->assertEquals($expectedids, $contextids);
}
/**
* Enable logging.
*
* @return void
*/
protected function enable_logging() {
set_config('enabled_stores', 'logstore_standard', 'tool_log');
set_config('buffersize', 0, 'logstore_standard');
set_config('logguests', 1, 'logstore_standard');
}
/**
* Get the contextlist for a user.
*
* @param object $user The user.
* @return contextlist
*/
protected function get_contextlist_for_user($user) {
$contextlist = new contextlist();
provider::add_contexts_for_userid($contextlist, $user->id);
return $contextlist;
}
}
+176
View File
@@ -0,0 +1,176 @@
<?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/>.
/**
* Data provider tests.
*
* @package tool_log
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use tool_log\privacy\provider;
require_once($CFG->dirroot . '/admin/tool/log/store/standard/tests/fixtures/event.php');
/**
* Data provider testcase class.
*
* We're not testing the full functionality, just that the provider passes the requests
* down to at least one of its subplugin. Each subplugin should have tests to cover the
* different provider methods in depth.
*
* @package tool_log
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_log_privacy_testcase extends provider_testcase {
public function setUp() {
$this->resetAfterTest();
$this->preventResetByRollback(); // Logging waits till the transaction gets committed.
}
public function test_get_contexts_for_userid() {
$admin = \core_user::get_user(2);
$u1 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c1ctx = context_course::instance($c1->id);
$this->enable_logging();
$manager = get_log_manager(true);
$this->setUser($u1);
$this->assertEmpty(provider::get_contexts_for_userid($u1->id)->get_contextids(), []);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$this->assertEquals($c1ctx->id, provider::get_contexts_for_userid($u1->id)->get_contextids()[0]);
}
public function test_delete_data_for_user() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c1ctx = context_course::instance($c1->id);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
// Confirm data present.
$this->assertTrue($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
// Delete all the things!
provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_standard', [$c1ctx->id]));
$this->assertFalse($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
$this->assertEquals(0, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
}
public function test_delete_data_for_all_users_in_context() {
global $DB;
$u1 = $this->getDataGenerator()->create_user();
$u2 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c1ctx = context_course::instance($c1->id);
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
// User 2 is the author.
$this->setUser($u2);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]);
$e->trigger();
// Confirm data present.
$this->assertTrue($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
$this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
// Delete all the things!
provider::delete_data_for_all_users_in_context($c1ctx);
$this->assertFalse($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
$this->assertEquals(0, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
$this->assertEquals(0, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
}
public function test_export_data_for_user() {
$admin = \core_user::get_user(2);
$u1 = $this->getDataGenerator()->create_user();
$c1 = $this->getDataGenerator()->create_course();
$c1ctx = context_course::instance($c1->id);
$path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_standard')];
$this->enable_logging();
$manager = get_log_manager(true);
// User 1 is the author.
$this->setUser($u1);
$e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx, 'other' => ['i' => 123]]);
$e->trigger();
// Confirm data present for u1.
provider::export_user_data(new approved_contextlist($u1, 'tool_log', [$c1ctx->id]));
$data = writer::with_context($c1ctx)->get_data($path);
$this->assertCount(1, $data->logs);
$this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
$this->assertSame(123, $data->logs[0]['other']['i']);
}
/**
* Enable logging.
*
* @return void
*/
protected function enable_logging() {
set_config('enabled_stores', 'logstore_standard', 'tool_log');
set_config('buffersize', 0, 'logstore_standard');
set_config('logguests', 1, 'logstore_standard');
}
}
File diff suppressed because one or more lines are too long
+9 -1
View File
@@ -129,6 +129,11 @@ define(['jquery',
* @return {Promise}
*/
PlanActions.prototype._callAndRefresh = function(calls, planData) {
// Because this function causes a refresh, we must track the JS completion from start to finish to prevent
// stale reference issues in Behat.
var callKey = 'tool_lp/planactions:_callAndRefresh-' + Math.floor(Math.random() * Math.floor(1000));
M.util.js_pending(callKey);
var self = this;
calls.push({
@@ -141,7 +146,10 @@ define(['jquery',
.then(function() {
self._renderView(arguments[arguments.length - 1]);
})
.fail(notification.exception);
.fail(notification.exception)
.always(function() {
return M.util.js_complete(callKey);
});
};
/**
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_lp.
*
* @package tool_lp
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lp\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_lp implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
+1
View File
@@ -292,3 +292,4 @@ $string['xcompetencieslinkedoutofy'] = '{$a->x} out of {$a->y} competencies link
$string['xcompetenciesproficientoutofy'] = '{$a->x} out of {$a->y} competencies are proficient';
$string['xcompetenciesproficientoutofyincourse'] = 'You are proficient in {$a->x} out of {$a->y} competencies in this course.';
$string['xplanscompletedoutofy'] = '{$a->x} out of {$a->y} learning plans completed for this template';
$string['privacy:metadata'] = 'The Learning plans plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_lpimportcsv.
*
* @package tool_lpimportcsv
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpimportcsv\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_lpimportcsv implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -53,3 +53,4 @@ $string['scaleconfiguration'] = 'Scale configuration';
$string['scalevalues'] = 'Scale values';
$string['shortname'] = 'Short name';
$string['taxonomy'] = 'Taxonomy';
$string['privacy:metadata'] = 'The Import competency framework plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_lpmigrate.
*
* @package tool_lpmigrate
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpmigrate\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_lpmigrate implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -69,3 +69,4 @@ $string['warningcouldnotremovemodulecompetency'] = 'The activity or resource com
$string['warningdestinationcoursecompetencyalreadyexists'] = 'The destination course competency already exists.';
$string['warningdestinationmodulecompetencyalreadyexists'] = 'The destination activity or resource competency already exists.';
$string['warnings'] = 'Warnings';
$string['privacy:metadata'] = 'The Competencies migration tool plugin does not store any personal data.';
@@ -310,6 +310,16 @@ class manager {
return true;
}
/**
* Remove older verification failures.
*
* @return void
*/
public function tidy_old_verification_failures() {
global $DB;
$DB->delete_records_select('messageinbound_messagelist', 'timecreated < :time', ['time' => time() - DAYSECS]);
}
/**
* Process a message and pass it through the Inbound Message handling systems.
*
@@ -0,0 +1,173 @@
<?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/>.
/**
* Data provider.
*
* @package tool_messageinbound
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_messageinbound\privacy;
defined('MOODLE_INTERNAL') || die();
use context;
use context_user;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
/**
* Data provider class.
*
* @package tool_messageinbound
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\plugin\provider {
/**
* Returns metadata.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
$collection->add_database_table('messageinbound_messagelist', [
'messageid' => 'privacy:metadata:messagelist:messageid',
'userid' => 'privacy:metadata:messagelist:userid',
'address' => 'privacy:metadata:messagelist:address',
'timecreated' => 'privacy:metadata:messagelist:timecreated',
], 'privacy:metadata:messagelist');
// Arguably the keys are handled by \core\message\inbound\address_manager and thus could/should be handled by core.
$collection->add_subsystem_link('core_userkey', [], 'privacy:metadata:coreuserkey');
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return \contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid($userid) {
$contextlist = new \core_privacy\local\request\contextlist();
// Always add the user context so we're sure we're not dodging user keys, besides it's not costly to do so.
$contextlist->add_user_context($userid);
return $contextlist;
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
if (!static::approved_contextlist_contains_my_context($contextlist)) {
// We only care about the user's user context.
return;
}
$userid = $contextlist->get_user()->id;
$context = context_user::instance($userid);
$path = [get_string('messageinbound', 'tool_messageinbound')];
// Export user keys.
\core_userkey\privacy\provider::export_userkeys($context, $path, 'messageinbound_handler');
// Export the message list.
$data = [];
$recordset = $DB->get_recordset('messageinbound_messagelist', ['userid' => $userid], 'timecreated, id');
foreach ($recordset as $record) {
$data[] = [
'received_at' => $record->address,
'timecreated' => transform::datetime($record->timecreated),
];
}
$recordset->close();
writer::with_context($context)->export_data($path, (object) ['messages_pending_validation' => $data]);
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(context $context) {
global $DB;
if ($context->contextlevel != CONTEXT_USER) {
return;
}
static::delete_user_data($context->instanceid);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
if (!static::approved_contextlist_contains_my_context($contextlist)) {
// We only care about the user's user context.
return;
}
static::delete_user_data($contextlist->get_user()->id);
}
/**
* Delete a user's data.
*
* @param int $userid The user ID.
* @return void
*/
protected static function delete_user_data($userid) {
global $DB;
$DB->delete_records_select('messageinbound_messagelist', 'userid = :userid', ['userid' => $userid]);
\core_userkey\privacy\provider::delete_userkeys('messageinbound_handler', $userid);
}
/**
* Return whether the contextlist contains our own context.
*
* @param approved_contextlist $contextlist The contextlist
* @return bool
*/
protected static function approved_contextlist_contains_my_context(approved_contextlist $contextlist) {
$userid = $contextlist->get_user()->id;
foreach ($contextlist->get_contexts() as $context) {
if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $userid) {
return true;
}
}
return false;
}
}
@@ -49,6 +49,7 @@ class cleanup_task extends \core\task\scheduled_task {
*/
public function execute() {
$manager = new \tool_messageinbound\manager();
return $manager->tidy_old_messages();
$manager->tidy_old_messages();
$manager->tidy_old_verification_failures();
}
}
@@ -24,7 +24,7 @@
$string['classname'] = 'Class name';
$string['component'] = 'Component';
$string['configmessageinboundhost'] = 'The address of the server that Moodle should check mail against. To specify a non-default port, you can use the [server]:[port], for example mail.example.com:587 format. If you leave this field blank, Moodle will use the default port for the type of mail server you specify.';
$string['configmessageinboundhost'] = 'The address of the server that Moodle should check mail against. To specify a non-default port, use [server]:[port], for example mail.example.com:587. If a port isn\'t specified, the default port for the type of mail server will be used.';
$string['defaultexpiration'] = 'Default address expiry period';
$string['defaultexpiration_help'] = 'When an email address is generated by the handler, it can be set to automatically expire after a period of time, so that it can no longer be used. It is advisable to set an expiry period.';
$string['description'] = 'Description';
@@ -94,6 +94,12 @@ $string['onehour'] = 'One hour';
$string['oneweek'] = 'One week';
$string['oneyear'] = 'One year';
$string['pluginname'] = 'Inbound message configuration';
$string['privacy:metadata:coreuserkey'] = 'User\'s keys to validate the email received';
$string['privacy:metadata:messagelist'] = 'A list of message identifiers which failed validation and requires further authorisation';
$string['privacy:metadata:messagelist:address'] = 'The address at which the email was sent';
$string['privacy:metadata:messagelist:messageid'] = 'The message ID';
$string['privacy:metadata:messagelist:timecreated'] = 'The time at which the record was made';
$string['privacy:metadata:messagelist:userid'] = 'The ID of user who need to approve the message';
$string['replysubjectprefix'] = 'Re:';
$string['requirevalidation'] = 'Validate sender address';
$string['name'] = 'Name';
@@ -0,0 +1,97 @@
<?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/>.
/**
* Manager tests.
*
* @package tool_messageinbound
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use tool_messageinbound\privacy\provider;
/**
* Manager testcase class.
*
* @package tool_messageinbound
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_messageinbound_manager_testcase extends provider_testcase {
public function setUp() {
global $CFG;
$this->resetAfterTest();
// Pretend the system is enabled.
$CFG->messageinbound_enabled = true;
$CFG->messageinbound_mailbox = 'mailbox';
$CFG->messageinbound_domain = 'example.com';
}
public function test_tidy_old_verification_failures() {
global $DB;
$now = time();
$stale = $now - DAYSECS - 1; // Make a second older because PHP Unit is too damn fast!!
$this->create_messagelist(['timecreated' => $now]);
$this->create_messagelist(['timecreated' => $now - HOURSECS]);
$this->create_messagelist(['timecreated' => $stale]);
$this->create_messagelist(['timecreated' => $stale - HOURSECS]);
$this->create_messagelist(['timecreated' => $stale - YEARSECS]);
$this->assertEquals(5, $DB->count_records('messageinbound_messagelist', []));
$this->assertEquals(3, $DB->count_records_select('messageinbound_messagelist', 'timecreated < :t', ['t' => $stale + 1]));
$manager = new \tool_messageinbound\manager();
$manager->tidy_old_verification_failures();
$this->assertEquals(2, $DB->count_records('messageinbound_messagelist', []));
$this->assertEquals(0, $DB->count_records_select('messageinbound_messagelist', 'timecreated < :t', ['t' => $stale + 1]));
}
/**
* Create a message to validate.
*
* @param array $params The params.
* @return stdClass
*/
protected function create_messagelist(array $params) {
global $DB, $USER;
$record = (object) array_merge([
'messageid' => 'abc',
'userid' => $USER->id,
'address' => 'text@example.com',
'timecreated' => time(),
], $params);
$record->id = $DB->insert_record('messageinbound_messagelist', $record);
return $record;
}
}
@@ -0,0 +1,201 @@
<?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/>.
/**
* Data provider tests.
*
* @package tool_messageinbound
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
use core_privacy\tests\provider_testcase;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\transform;
use core_privacy\local\request\writer;
use tool_messageinbound\privacy\provider;
/**
* Data provider testcase class.
*
* @package tool_messageinbound
* @category test
* @copyright 2018 Frédéric Massart
* @author Frédéric Massart <fred@branchup.tech>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_messageinbound_privacy_testcase extends provider_testcase {
public function setUp() {
global $CFG;
$this->resetAfterTest();
// Pretend the system is enabled.
$CFG->messageinbound_enabled = true;
$CFG->messageinbound_mailbox = 'mailbox';
$CFG->messageinbound_domain = 'example.com';
}
public function test_get_contexts_for_userid() {
$dg = $this->getDataGenerator();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$u1ctx = context_user::instance($u1->id);
$u2ctx = context_user::instance($u2->id);
$contexts = provider::get_contexts_for_userid($u1->id)->get_contexts();
$this->assertCount(1, $contexts);
$this->assertEquals($u1ctx->id, $contexts[0]->id);
$contexts = provider::get_contexts_for_userid($u2->id)->get_contexts();
$this->assertCount(1, $contexts);
$this->assertEquals($u2ctx->id, $contexts[0]->id);
}
public function test_delete_data_for_user() {
global $DB;
$dg = $this->getDataGenerator();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$u1ctx = context_user::instance($u1->id);
$u2ctx = context_user::instance($u2->id);
$addressmanager = new \core\message\inbound\address_manager();
$addressmanager->set_handler('\tool_messageinbound\message\inbound\invalid_recipient_handler');
$addressmanager->set_data(123);
// Create a user key for both users.
$addressmanager->generate($u1->id);
$addressmanager->generate($u2->id);
// Create a messagelist for both users.
$this->create_messagelist(['userid' => $u1->id]);
$this->create_messagelist(['userid' => $u2->id]);
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
// Passing another user's context does not do anything.
provider::delete_data_for_user(new approved_contextlist($u1, 'tool_messageinbound', [$u2ctx->id]));
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
// Deleting user 1.
provider::delete_data_for_user(new approved_contextlist($u1, 'tool_messageinbound', [$u1ctx->id]));
$this->assertFalse($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
$this->assertFalse($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
}
public function test_delete_data_for_all_users_in_context() {
global $DB;
$dg = $this->getDataGenerator();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$u1ctx = context_user::instance($u1->id);
$u2ctx = context_user::instance($u2->id);
$addressmanager = new \core\message\inbound\address_manager();
$addressmanager->set_handler('\tool_messageinbound\message\inbound\invalid_recipient_handler');
$addressmanager->set_data(123);
// Create a user key for both users.
$addressmanager->generate($u1->id);
$addressmanager->generate($u2->id);
// Create a messagelist for both users.
$this->create_messagelist(['userid' => $u1->id]);
$this->create_messagelist(['userid' => $u2->id]);
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
// Deleting user 1.
provider::delete_data_for_all_users_in_context($u1ctx);
$this->assertFalse($DB->record_exists('user_private_key', ['userid' => $u1->id, 'script' => 'messageinbound_handler']));
$this->assertTrue($DB->record_exists('user_private_key', ['userid' => $u2->id, 'script' => 'messageinbound_handler']));
$this->assertFalse($DB->record_exists('messageinbound_messagelist', ['userid' => $u1->id]));
$this->assertTrue($DB->record_exists('messageinbound_messagelist', ['userid' => $u2->id]));
}
public function test_export_data_for_user() {
$dg = $this->getDataGenerator();
$u1 = $dg->create_user();
$u2 = $dg->create_user();
$u1ctx = context_user::instance($u1->id);
$u2ctx = context_user::instance($u2->id);
$addressmanager = new \core\message\inbound\address_manager();
$addressmanager->set_handler('\tool_messageinbound\message\inbound\invalid_recipient_handler');
$addressmanager->set_data(123);
// Create a user key for both users.
$addressmanager->generate($u1->id);
$addressmanager->generate($u2->id);
// Create a messagelist for both users.
$this->create_messagelist(['userid' => $u1->id, 'address' => 'u1@example1.com']);
$this->create_messagelist(['userid' => $u1->id, 'address' => 'u1@example2.com']);
$this->create_messagelist(['userid' => $u2->id, 'address' => 'u2@example1.com']);
// Export for user.
$this->setUser($u1);
provider::export_user_data(new approved_contextlist($u1, 'tool_messageinbound', [$u1ctx->id, $u2ctx->id]));
$data = writer::with_context($u2ctx)->get_data([get_string('messageinbound', 'tool_messageinbound')]);
$this->assertEmpty($data);
$data = writer::with_context($u1ctx)->get_data([get_string('messageinbound', 'tool_messageinbound')]);
$this->assertCount(2, $data->messages_pending_validation);
$this->assertEquals('u1@example1.com', $data->messages_pending_validation[0]['received_at']);
$this->assertEquals('u1@example2.com', $data->messages_pending_validation[1]['received_at']);
$data = writer::with_context($u2ctx)->get_related_data([get_string('messageinbound', 'tool_messageinbound')], 'userkeys');
$this->assertEmpty($data);
$data = writer::with_context($u1ctx)->get_related_data([get_string('messageinbound', 'tool_messageinbound')], 'userkeys');
$this->assertCount(1, $data->keys);
$this->assertEquals('messageinbound_handler', $data->keys[0]->script);
}
/**
* Create a message to validate.
*
* @param array $params The params.
* @return stdClass
*/
protected function create_messagelist(array $params) {
global $DB, $USER;
$record = (object) array_merge([
'messageid' => 'abc',
'userid' => $USER->id,
'address' => 'text@example.com',
'timecreated' => time(),
], $params);
$record->id = $DB->insert_record('messageinbound_messagelist', $record);
return $record;
}
}
+3 -1
View File
@@ -211,7 +211,9 @@ class api {
}
if (empty($section) or $section == 'sitepolicies') {
$settings->sitepolicy = $CFG->sitepolicy;
$manager = new \core_privacy\local\sitepolicy\manager();
$settings->sitepolicy = ($sitepolicy = $manager->get_embed_url()) ? $sitepolicy->out(false) : '';
$settings->sitepolicyhandler = $CFG->sitepolicyhandler;
$settings->disableuserimages = $CFG->disableuserimages;
}
@@ -0,0 +1,142 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_mobile.
*
* @package tool_mobile
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_mobile\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\request\writer;
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\contextlist;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\transform;
/**
* Privacy provider for tool_mobile.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\user_preference_provider,
\core_privacy\local\request\plugin\provider {
/**
* Returns meta data about this system.
*
* @param collection $collection The initialised item collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection) {
// There is a one user preference.
$collection->add_user_preference('tool_mobile_autologin_request_last',
'privacy:metadata:preference:tool_mobile_autologin_request_last');
$collection->add_subsystem_link('core_userkey', [], 'privacy:metadata:core_userkey');
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid($userid) {
$sql = "SELECT ctx.id
FROM {user_private_key} k
JOIN {user} u ON k.userid = u.id
JOIN {context} ctx ON ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel
WHERE k.userid = :userid AND k.script = 'tool_mobile'";
$params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER];
$contextlist = new contextlist();
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
// If the user has data, then only the CONTEXT_USER should be present so get the first context.
$contexts = $contextlist->get_contexts();
if (count($contexts) == 0) {
return;
}
$context = reset($contexts);
// Sanity check that context is at the user context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
// Export associated userkeys.
\core_userkey\privacy\provider::export_userkeys($context, [], 'tool_mobile');
}
/**
* Export all user preferences for the plugin.
*
* @param int $userid The userid of the user whose data is to be exported.
*/
public static function export_user_preferences($userid) {
$autologinrequestlast = get_user_preferences('tool_mobile_autologin_request_last', null, $userid);
if ($autologinrequestlast !== null) {
$time = transform::datetime($autologinrequestlast);
writer::export_user_preference('tool_mobile',
'tool_mobile_autologin_request_last',
$time,
get_string('privacy:metadata:preference:tool_mobile_autologin_request_last', 'tool_mobile')
);
}
}
/**
* Delete all use data which matches the specified deletion_criteria.
*
* @param context $context A user context.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
// Sanity check that context is at the user context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
// Delete all the userkeys.
\core_userkey\privacy\provider::delete_userkeys('tool_mobile', $userid);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
// If the user has data, then only the user context should be present so get the first context.
$contexts = $contextlist->get_contexts();
if (count($contexts) == 0) {
return;
}
$context = reset($contexts);
// Sanity check that context is at the user context level, then get the userid.
if ($context->contextlevel !== CONTEXT_USER) {
return;
}
$userid = $context->instanceid;
// Delete all the userkeys.
\core_userkey\privacy\provider::delete_userkeys('tool_mobile', $userid);
}
}
+3 -1
View File
@@ -74,4 +74,6 @@ $string['smartappbanners'] = 'App Banners';
$string['pluginnotenabledorconfigured'] = 'Plugin not enabled or configured.';
$string['remoteaddons'] = 'Remote add-ons';
$string['typeoflogin'] = 'Type of login';
$string['typeoflogin_desc'] = 'If the site uses a SSO authentication method, then select via a browser window or via an embedded browser. An embedded browser provides a better user experience, though it doesn\'t work with all SSO plugins. If using SSO, autologinguests should be disabled.';
$string['typeoflogin_desc'] = 'If the site uses a SSO authentication method, then select via a browser window or via an embedded browser. An embedded browser provides a better user experience, though it doesn\'t work with all SSO plugins.';
$string['privacy:metadata:preference:tool_mobile_autologin_request_last'] = 'The date of the last auto-login key request. Between each request 6 minutes are required.';
$string['privacy:metadata:core_userkey'] = 'User\'s keys used to create auto-login key for the current user.';
@@ -150,6 +150,7 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
array('name' => 'newsitems', 'value' => $SITE->newsitems),
array('name' => 'commentsperpage', 'value' => $CFG->commentsperpage),
array('name' => 'sitepolicy', 'value' => $mysitepolicy),
array('name' => 'sitepolicyhandler', 'value' => ''),
array('name' => 'disableuserimages', 'value' => $CFG->disableuserimages),
array('name' => 'mygradesurl', 'value' => user_mygrades_url()->out(false)),
array('name' => 'tool_mobile_forcelogout', 'value' => 0),
@@ -0,0 +1,132 @@
<?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/>.
/**
* Base class for unit tests for tool_mobile.
*
* @package tool_mobile
* @category test
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\request\writer;
use \core_privacy\local\request\transform;
use \core_privacy\local\request\approved_contextlist;
use \tool_mobile\privacy\provider;
/**
* Unit tests for the tool_mobile implementation of the privacy API.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_mobile_privacy_testcase extends \core_privacy\tests\provider_testcase {
/**
* Basic setup for these tests.
*/
public function setUp() {
$this->resetAfterTest(true);
}
/**
* Test to check export_user_preferences.
* returns user preferences data.
*/
public function test_export_user_preferences() {
$user = $this->getDataGenerator()->create_user();
$expectedtime = time();
set_user_preference('tool_mobile_autologin_request_last', time(), $user);
provider::export_user_preferences($user->id);
$writer = writer::with_context(\context_system::instance());
$prefs = $writer->get_user_preferences('tool_mobile');
$time = transform::datetime($expectedtime);
$this->assertEquals($time, $prefs->tool_mobile_autologin_request_last->value);
$this->assertEquals(get_string('privacy:metadata:preference:tool_mobile_autologin_request_last', 'tool_mobile'),
$prefs->tool_mobile_autologin_request_last->description);
}
/**
* Test getting the context for the user ID related to this plugin.
*/
public function test_get_contexts_for_userid() {
// Create user and Mobile user keys.
$user = $this->getDataGenerator()->create_user();
$context = \context_user::instance($user->id);
$key = get_user_key('tool_mobile', $user->id);
$contextlist = provider::get_contexts_for_userid($user->id);
$this->assertEquals($context->id, $contextlist->current()->id);
}
/**
* Test that data is exported correctly for this plugin.
*/
public function test_export_user_data() {
global $DB;
// Create user and Mobile user keys.
$user = $this->getDataGenerator()->create_user();
$context = \context_user::instance($user->id);
$keyvalue = get_user_key('tool_mobile', $user->id);
$key = $DB->get_record('user_private_key', ['value' => $keyvalue]);
// Validate exported data.
$this->setUser($user);
$writer = writer::with_context($context);
$this->assertFalse($writer->has_any_data());
$this->export_context_data_for_user($user->id, $context, 'tool_mobile');
$userkeydata = $writer->get_related_data([], 'userkeys');
$this->assertCount(1, $userkeydata->keys);
$this->assertEquals($key->script, reset($userkeydata->keys)->script);
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context() {
global $DB;
// Create user and Mobile user keys.
$user = $this->getDataGenerator()->create_user();
$context = \context_user::instance($user->id);
$keyvalue = get_user_key('tool_mobile', $user->id);
$key = $DB->get_record('user_private_key', ['value' => $keyvalue]);
// Before deletion, we should have 1 user_private_key.
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile']);
$this->assertEquals(1, $count);
// Delete data.
provider::delete_data_for_all_users_in_context($context);
// After deletion, the user_private_key entries should have been deleted.
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile']);
$this->assertEquals(0, $count);
}
/**
* Test for provider::delete_data_for_user().
*/
public function test_delete_data_for_user() {
global $DB;
// Create user and Mobile user keys.
$user = $this->getDataGenerator()->create_user();
$context = \context_user::instance($user->id);
$keyvalue = get_user_key('tool_mobile', $user->id);
$key = $DB->get_record('user_private_key', ['value' => $keyvalue]);
// Before deletion, we should have 1 user_private_key.
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile']);
$this->assertEquals(1, $count);
// Delete data.
$contextlist = provider::get_contexts_for_userid($user->id);
$approvedcontextlist = new approved_contextlist($user, 'tool_mobile', $contextlist->get_contextids());
provider::delete_data_for_user($approvedcontextlist);
// After deletion, the user_private_key entries should have been deleted.
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile']);
$this->assertEquals(0, $count);
}
}
@@ -0,0 +1,213 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy class for requesting user data.
*
* @package tool_monitor
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_monitor\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\contextlist;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\transform;
use \core_privacy\local\request\writer;
use \tool_monitor\subscription_manager;
use \tool_monitor\rule_manager;
/**
* Privacy provider for tool_monitor
*
* @package tool_monitor
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\plugin\provider {
/**
* Get information about the user data stored by this plugin.
*
* @param collection $collection An object for storing metadata.
* @return collection The metadata.
*/
public static function get_metadata(collection $collection) {
$toolmonitorrules = [
'description' => 'privacy:metadata:description',
'name' => 'privacy:metadata:name',
'userid' => 'privacy:metadata:userid',
'plugin' => 'privacy:metadata:plugin',
'eventname' => 'privacy:metadata:eventname',
'template' => 'privacy:metadata:template',
'frequency' => 'privacy:metadata:frequency',
'timewindow' => 'privacy:metadata:timewindow',
'timemodified' => 'privacy:metadata:timemodifiedrule',
'timecreated' => 'privacy:metadata:timecreatedrule'
];
$toolmonitorsubscriptions = [
'userid' => 'privacy:metadata:useridsub',
'timecreated' => 'privacy:metadata:timecreatedsub',
'lastnotificationsent' => 'privacy:metadata:lastnotificationsent',
'inactivedate' => 'privacy:metadata:inactivedate'
];
// Tool monitor history doesn't look like it is used at all.
$toolmonitorhistory = [
'userid' => 'privacy:metadata:useridhistory',
'timesent' => 'privacy:metadata:timesent'
];
$collection->add_database_table('tool_monitor_rules', $toolmonitorrules, 'privacy:metadata:rulessummary');
$collection->add_database_table('tool_monitor_subscriptions', $toolmonitorsubscriptions,
'privacy:metadata:subscriptionssummary');
$collection->add_database_table('tool_monitor_history', $toolmonitorhistory, 'privacy:metadata:historysummary');
$collection->link_subsystem('core_message', 'privacy:metadata:messagesummary');
return $collection;
}
/**
* Return all contexts for this userid. In this situation the user context.
*
* @param int $userid The user ID.
* @return contextlist The list of context IDs.
*/
public static function get_contexts_for_userid($userid) {
$params = ['useridrules' => $userid, 'useridsubscriptions' => $userid, 'contextuserrule' => CONTEXT_USER,
'contextusersub' => CONTEXT_USER];
$sql = "SELECT DISTINCT ctx.id
FROM {context} ctx
LEFT JOIN {tool_monitor_rules} mr ON ctx.instanceid = mr.userid AND ctx.contextlevel = :contextuserrule
AND mr.userid = :useridsubscriptions
LEFT JOIN {tool_monitor_subscriptions} ms ON ctx.instanceid = ms.userid AND ctx.contextlevel = :contextusersub
AND ms.userid = :useridrules
WHERE ms.id IS NOT NULL OR mr.id IS NOT NULL";
$contextlist = new contextlist();
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Export all event monitor information for the list of contexts and this user.
*
* @param approved_contextlist $contextlist The list of approved contexts for a user.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
// Export rules.
$context = \context_user::instance($contextlist->get_user()->id);
$rules = $DB->get_records('tool_monitor_rules', ['userid' => $contextlist->get_user()->id]);
if ($rules) {
static::export_monitor_rules($rules, $context);
}
// Export subscriptions.
$subscriptions = subscription_manager::get_user_subscriptions(0, 0, $contextlist->get_user()->id);
if ($subscriptions) {
static::export_monitor_subscriptions($subscriptions, $context);
}
}
/**
* Delete all user data for this context.
*
* @param \context $context The context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
// Only delete data for user contexts.
if ($context->contextlevel == CONTEXT_USER) {
static::delete_user_data($context->instanceid);
}
}
/**
* Delete all user data for this user only.
*
* @param approved_contextlist $contextlist The list of approved contexts for a user.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
static::delete_user_data($contextlist->get_user()->id);
}
/**
* This does the deletion of user data for the event monitor.
*
* @param int $userid The user ID
*/
protected static function delete_user_data($userid) {
global $DB;
// Delete this user's subscriptions first.
subscription_manager::delete_user_subscriptions($userid);
// Because we only use user contexts the instance ID is the user ID.
// Get the rules and check if this user has the capability to delete them.
$rules = $DB->get_records('tool_monitor_rules', ['userid' => $userid]);
foreach ($rules as $ruledata) {
$rule = rule_manager::get_rule($ruledata);
// If no-one is suscribed to the rule then it is safe to delete.
if ($rule->can_manage_rule($userid) && subscription_manager::count_rule_subscriptions($rule->id) == 0) {
$rule->delete_rule();
}
}
}
/**
* This formats and then exports the monitor rules.
*
* @param array $rules The monitor rules.
* @param context_user $context The user context
*/
protected static function export_monitor_rules(array $rules, \context_user $context) {
foreach ($rules as $rule) {
$rule = rule_manager::get_rule($rule);
$ruledata = new \stdClass();
$ruledata->name = $rule->name;
$ruledata->eventname = $rule->get_event_name();
$ruledata->description = $rule->get_description($context);
$ruledata->plugin = $rule->get_plugin_name();
$ruledata->template = $rule->template;
$ruledata->frequency = $rule->get_filters_description();
$ruledata->course = $rule->get_course_name($context);
$ruledata->timecreated = transform::datetime($rule->timecreated);
$ruledata->timemodified = transform::datetime($rule->timemodified);
writer::with_context($context)->export_data([get_string('privacy:createdrules', 'tool_monitor'),
$rule->name . '_' . $rule->id], $ruledata);
}
}
/**
* This formats and then exports the event monitor subscriptions.
*
* @param array $subscriptions Subscriptions
* @param \context_user $context The user context
*/
protected static function export_monitor_subscriptions(array $subscriptions, \context_user $context) {
foreach ($subscriptions as $subscription) {
$subscriptiondata = new \stdClass();
$subscriptiondata->instancename = $subscription->get_instance_name();
$subscriptiondata->eventname = $subscription->get_event_name();
$subscriptiondata->frequency = $subscription->get_filters_description();
$subscriptiondata->name = $subscription->get_name($context);
$subscriptiondata->description = $subscription->get_description($context);
$subscriptiondata->pluginname = $subscription->get_plugin_name();
$subscriptiondata->course = $subscription->get_course_name($context);
$subscriptiondata->timecreated = transform::datetime($subscription->timecreated);
$subscriptiondata->lastnotificationsent = transform::datetime($subscription->lastnotificationsent);
writer::with_context($context)->export_data([get_string('privacy:subscriptions', 'tool_monitor'),
$subscriptiondata->name . '_' . $subscription->id, $subscriptiondata->course, $subscriptiondata->instancename],
$subscriptiondata);
}
}
}
+4 -3
View File
@@ -51,14 +51,15 @@ class rule {
}
/**
* Can the current user manage this rule?
* Can the user manage this rule? Defaults to $USER.
*
* @param int $userid Check against this userid.
* @return bool true if the current user can manage this rule, else false.
*/
public function can_manage_rule() {
public function can_manage_rule($userid = null) {
$courseid = $this->courseid;
$context = empty($courseid) ? \context_system::instance() : \context_course::instance($this->courseid);
return has_capability('tool/monitor:managerules', $context);
return has_capability('tool/monitor:managerules', $context, $userid);
}
/**
+3 -3
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="tool/monitor/db" VERSION="20141103" COMMENT="XMLDB file for Moodle tool/monitor"
<XMLDB PATH="admin/tool/monitor/db" VERSION="20141103" COMMENT="XMLDB file for Moodle tool/monitor"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="tool_monitor_rules" COMMENT="Table to store rules">
@@ -79,4 +79,4 @@
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
@@ -79,6 +79,28 @@ $string['monitor:managetool'] = 'Enable/disable event monitoring';
$string['monitor:subscribe'] = 'Subscribe to event monitor rules';
$string['norules'] = 'There are no event monitoring rules.';
$string['pluginname'] = 'Event monitor';
$string['privacy:createdrules'] = 'Event monitor rules I created';
$string['privacy:metadata:description'] = 'Description of the rule';
$string['privacy:metadata:eventname'] = 'Fully qualified name of the event';
$string['privacy:metadata:frequency'] = 'Frequency of notifications';
$string['privacy:metadata:historysummary'] = 'Stores the history of the message notifications sent';
$string['privacy:metadata:inactivedate'] = 'Period of time, in days, after which an inactive subscription will be removed completely';
$string['privacy:metadata:lastnotificationsent'] = 'When a notification was last sent for this subscription.';
$string['privacy:metadata:messagesummary'] = 'Notifications are sent to the message system.';
$string['privacy:metadata:name'] = 'Name of the rule';
$string['privacy:metadata:plugin'] = 'Frankenstlye name of the plugin';
$string['privacy:metadata:rulessummary'] = 'This stores monitor rules.';
$string['privacy:metadata:subscriptionssummary'] = 'Stores user subscriptions to various rules';
$string['privacy:metadata:template'] = 'Message template';
$string['privacy:metadata:timecreatedrule'] = 'When this rule was created';
$string['privacy:metadata:timecreatedsub'] = 'When this subscription was created';
$string['privacy:metadata:timemodifiedrule'] = 'When this rule was last modified';
$string['privacy:metadata:timesent'] = 'When the message was sent';
$string['privacy:metadata:timewindow'] = 'Time window in seconds';
$string['privacy:metadata:userid'] = 'The ID of user who created the rule.';
$string['privacy:metadata:useridhistory'] = 'The ID of the user to whom this notification was sent';
$string['privacy:metadata:useridsub'] = 'The ID of the subscriber.';
$string['privacy:subscriptions'] = 'My event monitor subscriptions';
$string['processevents'] = 'Process events';
$string['rulename'] = 'Rule name';
$string['ruleareyousure'] = 'Are you sure you want to delete the rule "{$a}"?';
+289
View File
@@ -0,0 +1,289 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy test for the event monitor
*
* @package tool_monitor
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use \tool_monitor\privacy\provider;
use \core_privacy\local\request\approved_contextlist;
/**
* Privacy test for the event monitor
*
* @package tool_monitor
* @category test
* @copyright 2018 Adrian Greeve <adriangreeve.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_monitor_privacy_testcase extends advanced_testcase {
/**
* Set up method.
*/
public function setUp() {
$this->resetAfterTest();
// Enable monitor.
set_config('enablemonitor', 1, 'tool_monitor');
}
/**
* Assign a capability to $USER
* The function creates a student $USER if $USER->id is empty
*
* @param string $capability capability name
* @param int $contextid
* @param int $roleid
* @return int the role id - mainly returned for creation, so calling function can reuse it
*/
public static function assign_user_capability($capability, $contextid, $roleid = null) {
global $USER;
// Create a new student $USER if $USER doesn't exist.
if (empty($USER->id)) {
$user = self::getDataGenerator()->create_user();
self::setUser($user);
}
if (empty($roleid)) {
$roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
}
assign_capability($capability, CAP_ALLOW, $roleid, $contextid);
role_assign($roleid, $USER->id, $contextid);
accesslib_clear_all_caches_for_unit_testing();
return $roleid;
}
/**
* Test that a collection with data is returned when calling this function.
*/
public function test_get_metadata() {
$collection = new \core_privacy\local\metadata\collection('tool_monitor');
$collection = provider::get_metadata($collection);
$this->assertNotEmpty($collection);
}
/**
* Check that a user context is returned if there is any user data for this user.
*/
public function test_get_contexts_for_userid() {
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$this->assertEmpty(provider::get_contexts_for_userid($user->id));
$this->assertEmpty(provider::get_contexts_for_userid($user2->id));
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
// Create a rule with this user.
$this->setUser($user);
$rule = $monitorgenerator->create_rule();
$contextlist = provider::get_contexts_for_userid($user->id);
// Check that we only get back one context.
$this->assertCount(1, $contextlist);
// Check that a context is returned for just creating a rule.
$this->assertEquals($usercontext->id, $contextlist->get_contextids()[0]);
$this->setUser($user2);
$record = new stdClass();
$record->courseid = 0;
$record->userid = $user2->id;
$record->ruleid = $rule->id;
$subscription = $monitorgenerator->create_subscription($record);
$contextlist = provider::get_contexts_for_userid($user2->id);
// Check that we only get back one context.
$this->assertCount(1, $contextlist);
// Check that a context is returned for just subscribing to a rule.
$this->assertEquals($usercontext2->id, $contextlist->get_contextids()[0]);
}
/**
* Test that user data is exported correctly.
*/
public function test_export_user_data() {
$user = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
$writer = \core_privacy\local\request\writer::with_context($usercontext);
$this->assertFalse($writer->has_any_data());
$approvedlist = new approved_contextlist($user, 'tool_monitor', [$usercontext->id]);
provider::export_user_data($approvedlist);
// Check that the rules created by this user are exported.
$this->assertEquals($rulerecord->name, $writer->get_data([get_string('privacy:createdrules', 'tool_monitor'),
$rulerecord->name . '_' . $rule->id])->name);
$this->assertEquals($secondrulerecord->name, $writer->get_data([get_string('privacy:createdrules', 'tool_monitor'),
$secondrulerecord->name . '_' . $rule2->id])->name);
// Check that the subscriptions for this user are also exported.
$this->assertEquals($rulerecord->name, $writer->get_data([get_string('privacy:subscriptions', 'tool_monitor'),
$rulerecord->name . '_' . $subscription->id, 'Site' , 'All events'])->name);
}
/**
* Test deleting all user data for a specific context.
*/
public function test_delete_data_for_all_users_in_context() {
global $DB;
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
// Need to give user one the ability to manage rules.
$this->assign_user_capability('tool/monitor:managerules', \context_system::instance());
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
// Have user 2 subscribe to the second rule created by user 1.
$subscription2 = (object)['ruleid' => $rule2->id, 'userid' => $user2->id];
$subscription2 = $monitorgenerator->create_subscription($subscription2);
$this->setUser($user2);
$thirdrulerecord = (object)['name' => 'privacy rule for second user'];
$rule3 = $monitorgenerator->create_rule($thirdrulerecord);
$subscription3 = (object)['ruleid' => $rule3->id, 'userid' => $user2->id];
$subscription3 = $monitorgenerator->create_subscription($subscription3);
// Try a different context first.
provider::delete_data_for_all_users_in_context(context_system::instance());
// Get all of the monitor rules.
$dbrules = $DB->get_records('tool_monitor_rules');
// All of the rules should still be present.
$this->assertCount(3, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule->id]->userid);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// Delete everything for the first user context.
provider::delete_data_for_all_users_in_context($usercontext);
// Get all of the monitor rules.
$dbrules = $DB->get_records('tool_monitor_rules');
// Only the rules for user 1 that does not have any more subscriptions should be deleted (the first rule).
$this->assertCount(2, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// Get all of the monitor subscriptions.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
// There should be two subscriptions left, both for user 2.
$this->assertCount(2, $dbsubs);
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
}
/**
* This should work identical to the above test.
*/
public function test_delete_data_for_user() {
global $DB;
$user = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$usercontext2 = \context_user::instance($user2->id);
$monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
$this->setUser($user);
// Need to give user one the ability to manage rules.
$this->assign_user_capability('tool/monitor:managerules', \context_system::instance());
$rulerecord = (object)['name' => 'privacy rule'];
$rule = $monitorgenerator->create_rule($rulerecord);
$secondrulerecord = (object)['name' => 'privacy rule2'];
$rule2 = $monitorgenerator->create_rule($secondrulerecord);
$subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
$subscription = $monitorgenerator->create_subscription($subscription);
// Have user 2 subscribe to the second rule created by user 1.
$subscription2 = (object)['ruleid' => $rule2->id, 'userid' => $user2->id];
$subscription2 = $monitorgenerator->create_subscription($subscription2);
$this->setUser($user2);
$thirdrulerecord = (object)['name' => 'privacy rule for second user'];
$rule3 = $monitorgenerator->create_rule($thirdrulerecord);
$subscription3 = (object)['ruleid' => $rule3->id, 'userid' => $user2->id];
$subscription3 = $monitorgenerator->create_subscription($subscription3);
$approvedlist = new approved_contextlist($user, 'tool_monitor', [$usercontext->id]);
// Delete everything for the first user.
provider::delete_data_for_user($approvedlist);
// Get all of the monitor rules.
$dbrules = $DB->get_records('tool_monitor_rules');
// Only the rules for user 1 that does not have any more subscriptions should be deleted (the first rule).
$this->assertCount(2, $dbrules);
$this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
$this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
// Get all of the monitor subscriptions.
$dbsubs = $DB->get_records('tool_monitor_subscriptions');
// There should be two subscriptions left, both for user 2.
$this->assertCount(2, $dbsubs);
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
}
}
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_multilangupgrade.
*
* @package tool_multilangupgrade
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_multilangupgrade\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_multilangupgrade implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -27,3 +27,4 @@ $string['multilangupgradeinfo'] = '<p>The multilang filter syntax was changed in
<p>Example: &lt;span lang="en" class="multilang"&gt;Hello!&lt;/span&gt;&lt;span lang="es" class="multilang"&gt;Hola!&lt;/span&gt;</p>
<p>Do you want to upgrade the syntax in all existing texts now?</p>';
$string['pluginname'] = 'Multilang upgrade';
$string['privacy:metadata'] = 'The Multilang upgrade plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_oauth2.
*
* @package tool_oauth2
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_oauth2\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_oauth2 implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -96,8 +96,10 @@ $string['systemauthstatus'] = 'System account connected';
$string['usebasicauth'] = 'Authenticate token requests via HTTP headers';
$string['usebasicauth_help'] = 'Utilise the HTTP Basic authentication scheme when sending client ID and password with a refresh token request. Recommended by the OAuth 2 standard, but may not be available with some issuers.';
$string['userfieldexternalfield'] = 'External field name';
$string['userfieldexternalfield_error'] = 'This field cannot contain HTML.';
$string['userfieldexternalfield_help'] = 'Name of the field provided by the external OAuth system.';
$string['userfieldinternalfield_help'] = 'Name of the Moodle user field that should be mapped from the external field.';
$string['userfieldinternalfield'] = 'Internal field name';
$string['userfieldmappingdeleted'] = 'User field mapping deleted';
$string['userfieldmappingsforissuer'] = 'User field mappings for issuer: {$a}';
$string['privacy:metadata'] = 'The OAuth 2 services plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_phpunit.
*
* @package tool_phpunit
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_phpunit\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_phpunit implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -23,3 +23,4 @@
*/
$string['pluginname'] = 'PHPUnit tests';
$string['privacy:metadata'] = 'The PHPUnit tests plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_profiling.
*
* @package tool_profiling
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_profiling\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_profiling implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -53,3 +53,4 @@ $string['summaryof'] = 'Summary of {$a}';
$string['viewdetails'] = 'View profiling details';
$string['viewdiff'] = 'View profiling differences with:';
$string['viewdiffdetails'] = 'View profiling diff details';
$string['privacy:metadata'] = 'The Profiling runs plugin does not store any personal data.';
+6 -2
View File
@@ -25,8 +25,12 @@
defined('MOODLE_INTERNAL') || die;
// profiling tool, added to development
if ((extension_loaded('xhprof') || extension_loaded('tideways')) && (!empty($CFG->profilingenabled) || !empty($CFG->earlyprofilingenabled))) {
// Profiling tool, added to development.
$hasextension = extension_loaded('tideways_xhprof');
$hasextension = $hasextension || extension_loaded('tideways');
$hasextension = $hasextension || extension_loaded('xhprof');
$isenabled = !empty($CFG->profilingenabled) || !empty($CFG->earlyprofilingenabled);
if ($hasextension && $isenabled) {
$ADMIN->add('development', new admin_externalpage('toolprofiling', get_string('pluginname', 'tool_profiling'),
"$CFG->wwwroot/$CFG->admin/tool/profiling/index.php", 'moodle/site:config'));
}
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_recyclebin.
*
* @package tool_recyclebin
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_recyclebin\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_recyclebin implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="tool/recyclebin/db" VERSION="20160315" COMMENT="XMLDB file for Moodle tool/recyclebin"
<XMLDB PATH="admin/tool/recyclebin/db" VERSION="20160315" COMMENT="XMLDB file for Moodle tool/recyclebin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="tool_recyclebin_course" COMMENT="A list of items in the course recycle bin">
@@ -38,4 +38,4 @@
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
@@ -55,3 +55,4 @@ $string['taskcleanupcoursebin'] = 'Cleanup course recycle bin';
$string['recyclebin:deleteitems'] = 'Delete recycle bin items';
$string['recyclebin:restoreitems'] = 'Restore recycle bin items';
$string['recyclebin:viewitems'] = 'View recycle bin items';
$string['privacy:metadata'] = 'The Recycle bin plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_replace.
*
* @package tool_replace
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_replace\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_replace implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}
@@ -39,3 +39,4 @@ $string['replacewithhelp'] = 'usually new server URL';
$string['searchwholedb'] = 'Search whole database for';
$string['searchwholedbhelp'] = 'usually previous server URL';
$string['shortenoversized'] = 'Shorten result if necessary';
$string['privacy:metadata'] = 'The DB search and replace plugin does not store any personal data.';
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_spamcleaner.
*
* @package tool_spamcleaner
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_spamcleaner\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_spamcleaner implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() {
return 'privacy:metadata';
}
}

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