Compare commits
324 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9236c6860 | |||
| 5dcd9c53e3 | |||
| 758066eda4 | |||
| 6a12f2de83 | |||
| fe8663110a | |||
| 0f6761962a | |||
| bc066df1f6 | |||
| 246b39cba9 | |||
| facd24b4c7 | |||
| b7b3b75b2c | |||
| 98ac97e2a0 | |||
| 9aa6e8bfa4 | |||
| 03a65d8916 | |||
| 5e430e98cb | |||
| 068f22aee0 | |||
| 99d570fef4 | |||
| 4a2bc331fb | |||
| 3fef39fc68 | |||
| 5d434d4d19 | |||
| 440113b457 | |||
| 41ff45a7a7 | |||
| fa4274319d | |||
| 06c5a9e6ff | |||
| ca3605500e | |||
| 6beb56ba1f | |||
| f83fc14e4d | |||
| 844eae52fb | |||
| cf304a8870 | |||
| 8ec36b0fe2 | |||
| 31a9ee8172 | |||
| d0308d8d76 | |||
| 144c240841 | |||
| 434c5f8a56 | |||
| 0ce4a24888 | |||
| bfd1dd07d8 | |||
| 51e05c09c3 | |||
| 02990bd6b9 | |||
| a66195b8b9 | |||
| ae7953ff01 | |||
| e5dc80a10c | |||
| f080964380 | |||
| 2ea79c66cf | |||
| 36b738c185 | |||
| 1a89875c36 | |||
| c29b6e8c15 | |||
| ff710b83c3 | |||
| c619279f5e | |||
| 5772b0fba2 | |||
| c89d473133 | |||
| 0e540897e6 | |||
| 27e2fe6981 | |||
| e35bc644de | |||
| 5d7d6cb52b | |||
| 913abd448b | |||
| dfe9aa213b | |||
| dc24b81fef | |||
| cff1f1943e | |||
| fe5d17b166 | |||
| cdda22dad7 | |||
| 641a281bef | |||
| e70b33b720 | |||
| 8578d28631 | |||
| c7a1ecd9f6 | |||
| 829adb5f21 | |||
| b6e79ab8d8 | |||
| 2ba2d02202 | |||
| 2d117605b8 | |||
| 237e1a85ce | |||
| 5cb64c1faa | |||
| e714f3cee9 | |||
| 16deaa8611 | |||
| ffa36a4bbe | |||
| 5ed65e12e1 | |||
| d1c15a50c9 | |||
| bc121625c3 | |||
| 251a824d8e | |||
| efde049bdf | |||
| 88498220a1 | |||
| dfdadbdbe2 | |||
| fb8b947963 | |||
| b844baf8be | |||
| 0c794fc199 | |||
| 2f4feacac7 | |||
| 7d7edc8820 | |||
| 18c838f586 | |||
| 21c63124ab | |||
| 350cefe41e | |||
| 47c56f3475 | |||
| 4b5ac4ceae | |||
| 8ed193c3ee | |||
| 40e430e634 | |||
| aaf94b8f75 | |||
| 18e6878f5a | |||
| 1041ccaf2e | |||
| fb7b0157c1 | |||
| 8827e7fc3f | |||
| b85ec901dd | |||
| 2faa795209 | |||
| ca5a9de8c5 | |||
| b9287872eb | |||
| 8b448de4b0 | |||
| 06588b2cc0 | |||
| e8e4566aaa | |||
| 94ccf35860 | |||
| cf0386e763 | |||
| a603f86d65 | |||
| 265e374204 | |||
| e62e93aa0d | |||
| d00a6f52b4 | |||
| 0c75121648 | |||
| 5681222a0b | |||
| a45b7aa7ee | |||
| 3093cc28f1 | |||
| 0ff581cece | |||
| b93a787b3e | |||
| 4ab37af070 | |||
| f85f002b37 | |||
| f7bdcf959f | |||
| 64abea941e | |||
| b9bebd0e36 | |||
| de703e70e7 | |||
| b35acd2249 | |||
| a45c466000 | |||
| 3b7f331372 | |||
| 3145f21de1 | |||
| f8550e7982 | |||
| ab0847d328 | |||
| 54339683ac | |||
| 65e260281b | |||
| f29bd28d6a | |||
| 9654f2cd71 | |||
| 2337078a30 | |||
| 29d9535277 | |||
| 4b162c766d | |||
| 606c17e6ef | |||
| daf44482e9 | |||
| 7da0e04ca3 | |||
| 45c42e01a3 | |||
| 74af3b176d | |||
| 7e9f55f138 | |||
| 7354b4ea0e | |||
| 9f6edf2171 | |||
| 511c9addfa | |||
| 8616e10e89 | |||
| 91406c9103 | |||
| aa383f1b47 | |||
| 8bb22c4544 | |||
| ff383cdd57 | |||
| 23e190ead5 | |||
| d997069c62 | |||
| 96cc77d435 | |||
| 1daf3fafc0 | |||
| 7522b6a2e3 | |||
| ece94bb4e2 | |||
| cd44d4e463 | |||
| 395c985759 | |||
| 684d866e20 | |||
| 3b2e8b4a0a | |||
| 816e06e809 | |||
| 6924954471 | |||
| 2875ff2934 | |||
| b1ddacfc8e | |||
| 6d353a7918 | |||
| f9e09bd963 | |||
| 4f657eeed9 | |||
| 60e57b8448 | |||
| 628f99bf45 | |||
| 68e670d8ea | |||
| af9b21a388 | |||
| de08d71fc8 | |||
| 4846674f5c | |||
| ac66136751 | |||
| 5617f26568 | |||
| ad81f22148 | |||
| aabf264460 | |||
| c22d3a30a1 | |||
| 64d3271039 | |||
| c83c2c0f47 | |||
| 5fdb912a82 | |||
| 7a06e15952 | |||
| b64f314662 | |||
| e5994e8c04 | |||
| 1fb4f49cca | |||
| 32b4b57b26 | |||
| fd7e75a8a5 | |||
| abd7d4394b | |||
| e4256cd769 | |||
| 5a6a4cef8b | |||
| 8721afb2c6 | |||
| 0e199a5aec | |||
| 320947908b | |||
| 2e55209603 | |||
| f8979fac97 | |||
| 6a33a850fc | |||
| 9164ab6e39 | |||
| 2af1421e34 | |||
| 5a9fa0fe57 | |||
| c1db07d55b | |||
| c5b7a25ee6 | |||
| 7cc665e9c7 | |||
| 05fd85142e | |||
| e62ea2b803 | |||
| 972142a9af | |||
| b25f3693bb | |||
| 369caa6183 | |||
| 00268741c2 | |||
| 605b0547de | |||
| eea1aff443 | |||
| 1bc5a5abe9 | |||
| be4ea98f29 | |||
| 845215d826 | |||
| 2a9c11965b | |||
| 8c3d8a68f7 | |||
| 969010296d | |||
| 87186b9710 | |||
| 539ad434cb | |||
| af4fa2a55b | |||
| 15aec0b054 | |||
| 7974bbcaf7 | |||
| b4cbad15de | |||
| fe1eb00c0f | |||
| 03df75c0de | |||
| 21c6513a7c | |||
| 8938d826d9 | |||
| e71a526011 | |||
| f3f6960d3e | |||
| 8952d3f100 | |||
| 0bb9e2d8d7 | |||
| 07b6c89868 | |||
| ffba0168b1 | |||
| 26a276cea1 | |||
| 3e2eb62931 | |||
| 62104652c8 | |||
| c950c91696 | |||
| 73e4f14d1b | |||
| 87d3c32f2e | |||
| b8e0488c90 | |||
| 6c23087aa7 | |||
| a6d9966786 | |||
| 1a8167e781 | |||
| 47dd1d85aa | |||
| c29edc7551 | |||
| fdddb80b70 | |||
| 70a804d98e | |||
| c12caea3d4 | |||
| 191a7fd205 | |||
| b0cb0168f4 | |||
| fb762d4e5c | |||
| ed0e988020 | |||
| 20cb5f4086 | |||
| de5d2667ab | |||
| 4a54efd42a | |||
| 5769d5fc86 | |||
| 0225f34969 | |||
| 23c69f1ef0 | |||
| 6e6b38e0b5 | |||
| 2e3892e951 | |||
| abe62e33e6 | |||
| 78731d0b96 | |||
| 56a58d538c | |||
| ef1c918973 | |||
| 3b9fce4e1c | |||
| 7b9e9eb98d | |||
| 0456d880f0 | |||
| 705776211a | |||
| 94b8228ba1 | |||
| 0b7d0d0f79 | |||
| c29501c06d | |||
| c152025706 | |||
| 0444dd2b70 | |||
| 15aded1e2a | |||
| cbff142b8e | |||
| ee16cb39bf | |||
| 7f0eba32de | |||
| 144c9ba7c3 | |||
| b676ff39a4 | |||
| fe709d665d | |||
| d692104051 | |||
| 17ebd603e1 | |||
| b24eb6c565 | |||
| c449504287 | |||
| 8df6b374bb | |||
| e84e1bbff3 | |||
| 3cfc322bdf | |||
| 6da402bf34 | |||
| 126c58ede4 | |||
| 6217d91173 | |||
| d28be61fb5 | |||
| a96ef27857 | |||
| 255541d592 | |||
| 19b4c997e9 | |||
| 93819366a4 | |||
| 7726e2e2d6 | |||
| d95ccdd4ec | |||
| 5698d90e6a | |||
| 44b87b5d95 | |||
| 334412f1cc | |||
| afcb4cd69a | |||
| d8a7c52ee6 | |||
| 05a70bac38 | |||
| 951f10fd3e | |||
| 10a5e2a8de | |||
| 82c32f9a80 | |||
| 17ae93679d | |||
| 27ffa62131 | |||
| 97a4db9c97 | |||
| 6f1a49b8b7 | |||
| 740807d2e3 | |||
| 066b01a788 | |||
| e7b4c991ee | |||
| 42ee1fc276 | |||
| d56935d66f | |||
| 9e2565d84d | |||
| 73c72b4148 | |||
| 244af9a0da | |||
| 2eb043fb36 | |||
| 2454da368a | |||
| 8e899e949d | |||
| 6b0b697fb8 | |||
| 9a854a2fc9 | |||
| b6f1cf03e3 | |||
| d26cdca687 | |||
| dbeee32b59 | |||
| 0a8663b425 |
+2
-4
@@ -3,8 +3,8 @@
|
||||
*/**/build/
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
@@ -41,6 +41,7 @@ lib/html2text/
|
||||
lib/markdown/
|
||||
lib/recaptchalib.php
|
||||
lib/xhprof/
|
||||
lib/xmlize.php
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
lib/amd/src/loglevel.js
|
||||
@@ -57,10 +58,7 @@ lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/amd/src/adapter.js
|
||||
lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
|
||||
+2
-4
@@ -4,8 +4,8 @@ theme/clean/style/custom.css
|
||||
theme/more/style/custom.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
@@ -42,6 +42,7 @@ lib/html2text/
|
||||
lib/markdown/
|
||||
lib/recaptchalib.php
|
||||
lib/xhprof/
|
||||
lib/xmlize.php
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
lib/amd/src/loglevel.js
|
||||
@@ -58,10 +59,7 @@ lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/amd/src/adapter.js
|
||||
lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
|
||||
+2
-2
@@ -207,7 +207,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_35_STABLE;
|
||||
git fetch upstream MOODLE_34_STABLE;
|
||||
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
|
||||
export GIT_COMMIT="$TRAVIS_COMMIT";
|
||||
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
|
||||
@@ -248,7 +248,7 @@ script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
|
||||
vendor/bin/phpunit;
|
||||
fi
|
||||
|
||||
- >
|
||||
|
||||
+2
-4
@@ -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,9 +129,7 @@ if ($savebutton) {
|
||||
$visiblepathtosection = array_reverse($settingspage->visiblepath);
|
||||
$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection));
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
if ($buttons) {
|
||||
$PAGE->set_button($buttons);
|
||||
}
|
||||
$PAGE->set_button($buttons);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* Privacy Subsystem implementation for core_admin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_admin\privacy;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for core_admin implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,6 @@ foreach ($rs as $user) {
|
||||
echo "Redeleting user $user->id: $user->username ($user->email)\n";
|
||||
delete_user($user);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
cli_heading('Deleting all leftovers');
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ $databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'n
|
||||
'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'),
|
||||
'oci' => moodle_database::get_driver_instance('oci', 'native'),
|
||||
'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // MS SQL*Server PHP driver
|
||||
'mssql' => moodle_database::get_driver_instance('mssql', 'native'), // FreeTDS driver
|
||||
);
|
||||
foreach ($databases as $type=>$database) {
|
||||
if ($database->driver_installed() !== true) {
|
||||
@@ -442,7 +443,6 @@ if ($interactive) {
|
||||
}
|
||||
}
|
||||
$CFG->tempdir = $CFG->dataroot.'/temp';
|
||||
$CFG->backuptempdir = $CFG->tempdir.'/backup';
|
||||
$CFG->cachedir = $CFG->dataroot.'/cache';
|
||||
$CFG->localcachedir = $CFG->dataroot.'/localcache';
|
||||
|
||||
|
||||
@@ -131,11 +131,10 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
cli_error(get_string('pluginschecktodo', 'admin'));
|
||||
}
|
||||
|
||||
$a = new stdClass();
|
||||
$a->oldversion = $oldversion;
|
||||
$a->newversion = $newversion;
|
||||
|
||||
if ($interactive) {
|
||||
$a = new stdClass();
|
||||
$a->oldversion = $oldversion;
|
||||
$a->newversion = $newversion;
|
||||
echo cli_heading(get_string('databasechecking', '', $a)) . PHP_EOL;
|
||||
}
|
||||
|
||||
@@ -194,5 +193,5 @@ admin_apply_default_settings(NULL, false);
|
||||
// to immediately start browsing the site.
|
||||
upgrade_themes();
|
||||
|
||||
echo get_string('cliupgradefinished', 'admin', $a)."\n";
|
||||
echo get_string('cliupgradefinished', 'admin')."\n";
|
||||
exit(0); // 0 means success
|
||||
|
||||
@@ -110,7 +110,7 @@ if (\core\hub\registration::is_registered()) {
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('core', 'admin');
|
||||
$renderer = $PAGE->get_renderer('core', 'register');
|
||||
echo $renderer->moodleorg_registration_message();
|
||||
|
||||
$siteregistrationform->display();
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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() {
|
||||
return format_text(get_string('registermoodlenet', 'admin'), FORMAT_HTML, ['noclean' => true]);
|
||||
}
|
||||
}
|
||||
@@ -2084,13 +2084,4 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
return $this->warning(get_string('legacylogginginuse'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display message about the benefits of registering on Moodle.org
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function moodleorg_registration_message() {
|
||||
return format_text(get_string('registermoodlenet', 'admin'), FORMAT_HTML, ['noclean' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ $mode = required_param('mode', PARAM_ALPHANUMEXT);
|
||||
$classformode = array(
|
||||
'assign' => 'core_role_allow_assign_page',
|
||||
'override' => 'core_role_allow_override_page',
|
||||
'switch' => 'core_role_allow_switch_page',
|
||||
'view' => 'core_role_allow_view_page'
|
||||
'switch' => 'core_role_allow_switch_page'
|
||||
);
|
||||
if (!isset($classformode[$mode])) {
|
||||
print_error('invalidmode', '', '', $mode);
|
||||
@@ -59,9 +58,6 @@ if (optional_param('submit', false, PARAM_BOOL) && data_submitted() && confirm_s
|
||||
case 'switch':
|
||||
$event = \core\event\role_allow_switch_updated::create(array('context' => $syscontext));
|
||||
break;
|
||||
case 'view':
|
||||
$event = \core\event\role_allow_view_updated::create(array('context' => $syscontext));
|
||||
break;
|
||||
}
|
||||
if ($event) {
|
||||
$event->trigger();
|
||||
|
||||
@@ -245,7 +245,7 @@ if ($roleid) {
|
||||
$select = new single_select($PAGE->url, 'roleid', $nameswithcounts, $roleid, null);
|
||||
$select->label = get_string('assignanotherrole', 'core_role');
|
||||
echo $OUTPUT->render($select);
|
||||
echo '<p><a href="' . $url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
|
||||
echo '<p><a href="' . $PAGE->url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
|
||||
echo '</div>';
|
||||
|
||||
} else if (empty($assignableroles)) {
|
||||
|
||||
@@ -33,7 +33,7 @@ class core_role_allow_assign_page extends core_role_allow_role_page {
|
||||
}
|
||||
|
||||
protected function set_allow($fromroleid, $targetroleid) {
|
||||
core_role_set_assign_allowed($fromroleid, $targetroleid);
|
||||
allow_assign($fromroleid, $targetroleid);
|
||||
}
|
||||
|
||||
protected function get_cell_tooltip($fromrole, $targetrole) {
|
||||
|
||||
@@ -33,7 +33,7 @@ class core_role_allow_override_page extends core_role_allow_role_page {
|
||||
}
|
||||
|
||||
protected function set_allow($fromroleid, $targetroleid) {
|
||||
core_role_set_override_allowed($fromroleid, $targetroleid);
|
||||
allow_override($fromroleid, $targetroleid);
|
||||
}
|
||||
|
||||
protected function get_cell_tooltip($fromrole, $targetrole) {
|
||||
|
||||
@@ -41,7 +41,7 @@ class core_role_allow_switch_page extends core_role_allow_role_page {
|
||||
}
|
||||
|
||||
protected function set_allow($fromroleid, $targetroleid) {
|
||||
core_role_set_switch_allowed($fromroleid, $targetroleid);
|
||||
allow_switch($fromroleid, $targetroleid);
|
||||
}
|
||||
|
||||
protected function is_allowed_target($targetroleid) {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Role view matrix.
|
||||
*
|
||||
* @package core_role
|
||||
* @copyright 2016 onwards Andrew Hancox <andrewdchancox@googlemail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Subclass of role_allow_role_page for the Allow views tab.
|
||||
*
|
||||
* @package core_role
|
||||
* @copyright 2016 onwards Andrew Hancox <andrewdchancox@googlemail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_role_allow_view_page extends core_role_allow_role_page {
|
||||
/** @var array */
|
||||
protected $allowedtargetroles;
|
||||
|
||||
/**
|
||||
* core_role_allow_view_page constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct('role_allow_view', 'allowview');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow from role to view target role.
|
||||
* @param int $fromroleid
|
||||
* @param int $targetroleid
|
||||
*/
|
||||
protected function set_allow($fromroleid, $targetroleid) {
|
||||
core_role_set_view_allowed($fromroleid, $targetroleid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tool tip for cell.
|
||||
* @param string $fromrole
|
||||
* @param string $targetrole
|
||||
* @return string
|
||||
* @throws \coding_exception
|
||||
*/
|
||||
protected function get_cell_tooltip($fromrole, $targetrole) {
|
||||
$a = new stdClass;
|
||||
$a->fromrole = $fromrole->localname;
|
||||
$a->targetrole = $targetrole->localname;
|
||||
return get_string('allowroletoview', 'core_role', $a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get intro text for role allow view page.
|
||||
* @return string
|
||||
* @throws \coding_exception
|
||||
*/
|
||||
public function get_intro_text() {
|
||||
return get_string('configallowview', 'core_admin');
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
protected $allowassign;
|
||||
protected $allowoverride;
|
||||
protected $allowswitch;
|
||||
protected $allowview;
|
||||
|
||||
public function __construct($context, $roleid) {
|
||||
$this->roleid = $roleid;
|
||||
@@ -73,7 +72,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$this->allowassign = array_keys($this->get_allow_roles_list('assign'));
|
||||
$this->allowoverride = array_keys($this->get_allow_roles_list('override'));
|
||||
$this->allowswitch = array_keys($this->get_allow_roles_list('switch'));
|
||||
$this->allowview = array_keys($this->get_allow_roles_list('view'));
|
||||
|
||||
} else {
|
||||
$this->role = new stdClass;
|
||||
@@ -85,7 +83,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$this->allowassign = array();
|
||||
$this->allowoverride = array();
|
||||
$this->allowswitch = array();
|
||||
$this->allowview = array();
|
||||
}
|
||||
parent::load_current_permissions();
|
||||
}
|
||||
@@ -103,8 +100,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$this->role->shortname = core_text::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
|
||||
if (empty($this->role->shortname)) {
|
||||
$this->errors['shortname'] = get_string('errorbadroleshortname', 'core_role');
|
||||
} else if (core_text::strlen($this->role->shortname) > 100) { // Check if it exceeds the max of 100 characters.
|
||||
$this->errors['shortname'] = get_string('errorroleshortnametoolong', 'core_role');
|
||||
}
|
||||
}
|
||||
if ($DB->record_exists_select('role', 'shortname = ? and id <> ?', array($this->role->shortname, $this->roleid))) {
|
||||
@@ -167,10 +162,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
if (!is_null($allow)) {
|
||||
$this->allowswitch = $allow;
|
||||
}
|
||||
$allow = optional_param_array('allowview', null, PARAM_INT);
|
||||
if (!is_null($allow)) {
|
||||
$this->allowview = $allow;
|
||||
}
|
||||
|
||||
// Now read the permissions for each capability.
|
||||
parent::read_submitted_permissions();
|
||||
@@ -187,8 +178,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
* @param int $roleid role id or 0 for no role
|
||||
* @param array $options array with following keys:
|
||||
* 'name', 'shortname', 'description', 'permissions', 'archetype',
|
||||
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch',
|
||||
* 'allowview'
|
||||
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
|
||||
*/
|
||||
public function force_duplicate($roleid, array $options) {
|
||||
global $DB;
|
||||
@@ -225,9 +215,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
if ($options['allowswitch']) {
|
||||
$this->allowswitch = array();
|
||||
}
|
||||
if ($options['allowview']) {
|
||||
$this->allowview = array();
|
||||
}
|
||||
|
||||
if ($options['permissions']) {
|
||||
foreach ($this->capabilities as $capid => $cap) {
|
||||
@@ -273,9 +260,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
if ($options['allowswitch']) {
|
||||
$this->allowswitch = array_keys($this->get_allow_roles_list('switch', $roleid));
|
||||
}
|
||||
if ($options['allowview']) {
|
||||
$this->allowview = array_keys($this->get_allow_roles_list('view', $roleid));
|
||||
}
|
||||
|
||||
if ($options['permissions']) {
|
||||
$this->permissions = $DB->get_records_menu('role_capabilities',
|
||||
@@ -296,8 +280,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
* @param string $archetype
|
||||
* @param array $options array with following keys:
|
||||
* 'name', 'shortname', 'description', 'permissions', 'archetype',
|
||||
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch',
|
||||
* 'allowview'
|
||||
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
|
||||
*/
|
||||
public function force_archetype($archetype, array $options) {
|
||||
$archetypes = get_role_archetypes();
|
||||
@@ -338,9 +321,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
if ($options['allowswitch']) {
|
||||
$this->allowswitch = get_default_role_archetype_allows('switch', $archetype);
|
||||
}
|
||||
if ($options['allowview']) {
|
||||
$this->allowview = get_default_role_archetype_allows('view', $archetype);
|
||||
}
|
||||
|
||||
if ($options['permissions']) {
|
||||
$defaultpermissions = get_default_capabilities($archetype);
|
||||
@@ -360,8 +340,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
* @param string $xml
|
||||
* @param array $options array with following keys:
|
||||
* 'name', 'shortname', 'description', 'permissions', 'archetype',
|
||||
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch',
|
||||
* 'allowview'
|
||||
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
|
||||
*/
|
||||
public function force_preset($xml, array $options) {
|
||||
if (!$info = core_role_preset::parse_preset($xml)) {
|
||||
@@ -398,7 +377,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array('assign', 'override', 'switch', 'view') as $type) {
|
||||
foreach (array('assign', 'override', 'switch') as $type) {
|
||||
if ($options['allow'.$type]) {
|
||||
if (isset($info['allow'.$type])) {
|
||||
$this->{'allow'.$type} = $info['allow'.$type];
|
||||
@@ -459,7 +438,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$this->save_allow('assign');
|
||||
$this->save_allow('override');
|
||||
$this->save_allow('switch');
|
||||
$this->save_allow('view');
|
||||
|
||||
// Permissions.
|
||||
parent::save_changes();
|
||||
@@ -471,7 +449,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$current = array_keys($this->get_allow_roles_list($type));
|
||||
$wanted = $this->{'allow'.$type};
|
||||
|
||||
$addfunction = "core_role_set_{$type}_allowed";
|
||||
$addfunction = 'allow_'.$type;
|
||||
$deltable = 'role_allow_'.$type;
|
||||
$field = 'allow'.$type;
|
||||
|
||||
@@ -498,7 +476,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
}
|
||||
|
||||
protected function get_shortname_field($id) {
|
||||
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="100" value="' . s($this->role->shortname) . '"' .
|
||||
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->shortname) . '"' .
|
||||
' class="form-control"/>';
|
||||
}
|
||||
|
||||
@@ -528,11 +506,9 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
if (!$this->disabled) {
|
||||
$output .= '<input type="hidden" name="contextlevel' . $cl . '" value="0" />';
|
||||
}
|
||||
$output .= '<div class="form-check justify-content-start w-100">';
|
||||
$output .= '<input class="form-check-input" type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl .
|
||||
$output .= '<input type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl .
|
||||
'" value="1" ' . $extraarguments . '/> ';
|
||||
$output .= '<label class="form-check-label" for="cl' . $cl . '">' . $clname . "</label>\n";
|
||||
$output .= '</div>';
|
||||
$output .= '<label for="cl' . $cl . '">' . $clname . "</label><br />\n";
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
@@ -547,7 +523,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
protected function get_allow_roles_list($type, $roleid = null) {
|
||||
global $DB;
|
||||
|
||||
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override' and $type !== 'view') {
|
||||
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
|
||||
debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
|
||||
return array();
|
||||
}
|
||||
@@ -571,11 +547,11 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
/**
|
||||
* Returns an array of roles with the allowed type.
|
||||
*
|
||||
* @param string $type Must be one of: assign, switch, override or view.
|
||||
* @param string $type Must be one of: assign, switch, or override.
|
||||
* @return array Am array of role names with the allowed type
|
||||
*/
|
||||
protected function get_allow_role_control($type) {
|
||||
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override' and $type !== 'view') {
|
||||
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
|
||||
debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
|
||||
return '';
|
||||
}
|
||||
@@ -665,7 +641,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$this->print_field('menuallowassign', get_string('allowassign', 'core_role'), $this->get_allow_role_control('assign'));
|
||||
$this->print_field('menuallowoverride', get_string('allowoverride', 'core_role'), $this->get_allow_role_control('override'));
|
||||
$this->print_field('menuallowswitch', get_string('allowswitch', 'core_role'), $this->get_allow_role_control('switch'));
|
||||
$this->print_field('menuallowview', get_string('allowview', 'core_role'), $this->get_allow_role_control('view'));
|
||||
if ($risks = $this->get_role_risks_info()) {
|
||||
$this->print_field('', get_string('rolerisks', 'core_role'), $risks);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class core_role_preset {
|
||||
$contextlevels->appendChild($dom->createElement('level', $name));
|
||||
}
|
||||
|
||||
foreach (array('assign', 'override', 'switch', 'view') as $type) {
|
||||
foreach (array('assign', 'override', 'switch') as $type) {
|
||||
$allows = $dom->createElement('allow'.$type);
|
||||
$top->appendChild($allows);
|
||||
$records = $DB->get_records('role_allow_'.$type, array('roleid'=>$roleid), "allow$type ASC");
|
||||
@@ -205,7 +205,7 @@ class core_role_preset {
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array('assign', 'override', 'switch', 'view') as $type) {
|
||||
foreach (array('assign', 'override', 'switch') as $type) {
|
||||
$values = self::get_node_children_values($dom, '/role/allow'.$type, 'shortname');
|
||||
if (!isset($values)) {
|
||||
$info['allow'.$type] = null;
|
||||
|
||||
@@ -79,7 +79,6 @@ class core_role_preset_form extends moodleform {
|
||||
$mform->addElement('advcheckbox', 'allowassign', get_string('allowassign', 'core_role'));
|
||||
$mform->addElement('advcheckbox', 'allowoverride', get_string('allowoverride', 'core_role'));
|
||||
$mform->addElement('advcheckbox', 'allowswitch', get_string('allowswitch', 'core_role'));
|
||||
$mform->addElement('advcheckbox', 'allowview', get_string('allowview', 'core_role'));
|
||||
$mform->addElement('advcheckbox', 'permissions', get_string('permissions', 'core_role'));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,379 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* Privacy Subsystem implementation for core_role.
|
||||
*
|
||||
* @package core_role
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_role\privacy;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use \core_privacy\local\metadata\collection;
|
||||
use \core_privacy\local\request\contextlist;
|
||||
use \core_privacy\local\request\approved_contextlist;
|
||||
use \core_privacy\local\request\transform;
|
||||
use \core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* 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) : collection {
|
||||
$rolecapabilities = [
|
||||
'roleid' => 'privacy:metadata:role_capabilities:roleid',
|
||||
'capability' => 'privacy:metadata:role_capabilities:capability',
|
||||
'permission' => 'privacy:metadata:role_capabilities:permission',
|
||||
'timemodified' => 'privacy:metadata:role_capabilities:timemodified',
|
||||
'modifierid' => 'privacy:metadata:role_capabilities:modifierid'
|
||||
];
|
||||
$roleassignments = [
|
||||
'roleid' => 'privacy:metadata:role_assignments:roleid',
|
||||
'userid' => 'privacy:metadata:role_assignments:userid',
|
||||
'timemodified' => 'privacy:metadata:role_assignments:timemodified',
|
||||
'modifierid' => 'privacy:metadata:role_assignments:modifierid',
|
||||
'component' => 'privacy:metadata:role_assignments:component',
|
||||
'itemid' => 'privacy:metadata:role_assignments:itemid'
|
||||
];
|
||||
$collection->add_database_table('role_capabilities', $rolecapabilities,
|
||||
'privacy:metadata:role_capabilities:tableexplanation');
|
||||
$collection->add_database_table('role_assignments', $roleassignments,
|
||||
'privacy:metadata:role_assignments:tableexplanation');
|
||||
|
||||
$collection->add_user_preference('definerole_showadvanced',
|
||||
'privacy:metadata:preference:showadvanced');
|
||||
|
||||
return $collection;
|
||||
}
|
||||
/**
|
||||
* Export all user preferences for the plugin.
|
||||
*
|
||||
* @param int $userid The userid of the user whose data is to be exported.
|
||||
*/
|
||||
public static function export_user_preferences(int $userid) {
|
||||
$showadvanced = get_user_preferences('definerole_showadvanced', null, $userid);
|
||||
if ($showadvanced !== null) {
|
||||
writer::export_user_preference('core_role',
|
||||
'definerole_showadvanced',
|
||||
transform::yesno($showadvanced),
|
||||
get_string('privacy:metadata:preference:showadvanced', 'core_role')
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Return all contexts for this userid.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
* @return contextlist The list of context IDs.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid) : contextlist {
|
||||
global $DB;
|
||||
|
||||
$contextlist = new contextlist();
|
||||
|
||||
// The role_capabilities table contains user data.
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT ctx.id
|
||||
FROM {context} ctx
|
||||
JOIN {role_capabilities} rc
|
||||
ON rc.contextid = ctx.id
|
||||
AND ((ctx.contextlevel {$insql} AND rc.modifierid = :modifierid)
|
||||
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))";
|
||||
$params = [
|
||||
'modifierid' => $userid,
|
||||
'contextlevel' => CONTEXT_USER,
|
||||
'userid' => $userid
|
||||
];
|
||||
$params += $inparams;
|
||||
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
// The role_assignments table contains user data.
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
'modifierid' => $userid
|
||||
];
|
||||
$params += $inparams;
|
||||
$sql = "SELECT ctx.id
|
||||
FROM {role_assignments} ra
|
||||
JOIN {context} ctx
|
||||
ON ctx.id = ra.contextid
|
||||
AND ctx.contextlevel {$insql}
|
||||
WHERE (ra.userid = :userid
|
||||
OR ra.modifierid = :modifierid)
|
||||
AND ra.component != 'tool_cohortroles'";
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The list of approved contexts for a user.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
if (empty($contextlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rolesnames = self::get_roles_name();
|
||||
$userid = $contextlist->get_user()->id;
|
||||
$ctxfields = \context_helper::get_preload_record_columns_sql('ctx');
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
|
||||
|
||||
// Role Assignments export data.
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, $ctxfields
|
||||
FROM {role_assignments} ra
|
||||
JOIN {context} ctx
|
||||
ON ctx.id = ra.contextid
|
||||
AND ctx.contextlevel {$inctxsql}
|
||||
AND (ra.userid = :userid OR ra.modifierid = :modifierid)
|
||||
AND ra.component != 'tool_cohortroles'
|
||||
JOIN {role} r
|
||||
ON r.id = ra.roleid
|
||||
WHERE ctx.id {$insql}";
|
||||
$params = ['userid' => $userid, 'modifierid' => $userid];
|
||||
$params += $inparams;
|
||||
$params += $ctxparams;
|
||||
$assignments = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($assignments as $assignment) {
|
||||
\context_helper::preload_from_record($assignment);
|
||||
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
|
||||
'timemodified' => transform::datetime($assignment->timemodified),
|
||||
'userid' => transform::user($assignment->userid),
|
||||
'modifierid' => transform::user($assignment->modifierid)
|
||||
];
|
||||
}
|
||||
$assignments->close();
|
||||
if (!empty($alldata)) {
|
||||
array_walk($alldata, function($roledata, $contextid) {
|
||||
$context = \context::instance_by_id($contextid);
|
||||
array_walk($roledata, function($data, $rolename) use ($context) {
|
||||
writer::with_context($context)->export_data(
|
||||
[get_string('privacy:metadata:role_assignments', 'core_role'), $rolename],
|
||||
(object)$data);
|
||||
});
|
||||
});
|
||||
unset($alldata);
|
||||
}
|
||||
|
||||
// Role Capabilities export data.
|
||||
$strpermissions = self::get_permissions_name();
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT rc.id, rc.contextid, rc.capability, rc.permission, rc.timemodified, rc.roleid, $ctxfields
|
||||
FROM {context} ctx
|
||||
JOIN {role_capabilities} rc
|
||||
ON rc.contextid = ctx.id
|
||||
AND ((ctx.contextlevel {$inctxsql} AND rc.modifierid = :modifierid)
|
||||
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))
|
||||
WHERE ctx.id {$insql}";
|
||||
$params = [
|
||||
'modifierid' => $userid,
|
||||
'contextlevel' => CONTEXT_USER,
|
||||
'userid' => $userid
|
||||
];
|
||||
$params += $inparams;
|
||||
$params += $ctxparams;
|
||||
$capabilities = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($capabilities as $capability) {
|
||||
\context_helper::preload_from_record($capability);
|
||||
$alldata[$capability->contextid][$rolesnames[$capability->roleid]][] = (object)[
|
||||
'timemodified' => transform::datetime($capability->timemodified),
|
||||
'capability' => $capability->capability,
|
||||
'permission' => $strpermissions[$capability->permission]
|
||||
];
|
||||
}
|
||||
$capabilities->close();
|
||||
if (!empty($alldata)) {
|
||||
array_walk($alldata, function($capdata, $contextid) {
|
||||
$context = \context::instance_by_id($contextid);
|
||||
array_walk($capdata, function($data, $rolename) use ($context) {
|
||||
writer::with_context($context)->export_data(
|
||||
[get_string('privacy:metadata:role_capabilities', 'core_role'), $rolename],
|
||||
(object)$data);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Exports the data relating to tool_cohortroles component on role assignments by
|
||||
* Assign user roles to cohort feature.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
*/
|
||||
public static function export_user_role_to_cohort(int $userid) {
|
||||
global $DB;
|
||||
|
||||
$rolesnames = self::get_roles_name();
|
||||
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, r.id as roleid
|
||||
FROM {role_assignments} ra
|
||||
JOIN {context} ctx
|
||||
ON ctx.id = ra.contextid
|
||||
AND ctx.contextlevel = :contextlevel
|
||||
AND ra.component = 'tool_cohortroles'
|
||||
JOIN {role} r
|
||||
ON r.id = ra.roleid
|
||||
WHERE ctx.instanceid = :instanceid
|
||||
OR ra.userid = :userid";
|
||||
$params = ['userid' => $userid, 'instanceid' => $userid, 'contextlevel' => CONTEXT_USER];
|
||||
$assignments = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($assignments as $assignment) {
|
||||
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
|
||||
'timemodified' => transform::datetime($assignment->timemodified),
|
||||
'userid' => transform::user($assignment->userid),
|
||||
'modifierid' => transform::user($assignment->modifierid)
|
||||
];
|
||||
}
|
||||
$assignments->close();
|
||||
if (!empty($alldata)) {
|
||||
array_walk($alldata, function($roledata, $contextid) {
|
||||
$context = \context::instance_by_id($contextid);
|
||||
array_walk($roledata, function($data, $rolename) use ($context) {
|
||||
writer::with_context($context)->export_related_data(
|
||||
[get_string('privacy:metadata:role_cohortroles', 'core_role'), $rolename], 'cohortroles',
|
||||
(object)$data);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Delete all user data for this context.
|
||||
*
|
||||
* @param \context $context The context to delete data for.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
global $DB;
|
||||
|
||||
// Don't remove data from role_capabilities.
|
||||
// Because this data affects the whole Moodle, there are override capabilities.
|
||||
// Don't belong to the modifier user.
|
||||
|
||||
// Remove data from role_assignments.
|
||||
$DB->delete_records('role_assignments', ['contextid' => $context->id]);
|
||||
}
|
||||
/**
|
||||
* Delete 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(int $userid) {
|
||||
global $DB;
|
||||
|
||||
// Delete entries where userid is a mentor by tool_cohortroles.
|
||||
$DB->delete_records('role_assignments', ['userid' => $userid, 'component' => 'tool_cohortroles']);
|
||||
}
|
||||
/**
|
||||
* Get all the localised roles name in a simple array.
|
||||
*
|
||||
* @return array Array of name of the roles by roleid.
|
||||
*/
|
||||
protected static function get_roles_name() {
|
||||
$roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
|
||||
$rolesnames = array();
|
||||
foreach ($roles as $role) {
|
||||
$rolesnames[$role->id] = $role->localname;
|
||||
}
|
||||
return $rolesnames;
|
||||
}
|
||||
/**
|
||||
* Get all the permissions name in a simple array.
|
||||
*
|
||||
* @return array Array of permissions name.
|
||||
*/
|
||||
protected static function get_permissions_name() {
|
||||
$strpermissions = array(
|
||||
CAP_INHERIT => get_string('inherit', 'role'),
|
||||
CAP_ALLOW => get_string('allow', 'role'),
|
||||
CAP_PREVENT => get_string('prevent', 'role'),
|
||||
CAP_PROHIBIT => get_string('prohibit', 'role')
|
||||
);
|
||||
return $strpermissions;
|
||||
}
|
||||
}
|
||||
@@ -103,8 +103,7 @@ if ($action === 'add' and $resettype !== 'none') {
|
||||
'contextlevels' => 1,
|
||||
'allowassign' => 1,
|
||||
'allowoverride' => 1,
|
||||
'allowswitch' => 1,
|
||||
'allowview' => 1);
|
||||
'allowswitch' => 1);
|
||||
if ($showadvanced) {
|
||||
$definitiontable = new core_role_define_role_table_advanced($systemcontext, 0);
|
||||
} else {
|
||||
@@ -151,8 +150,7 @@ if ($action === 'add' and $resettype !== 'none') {
|
||||
'contextlevels' => $data->contextlevels,
|
||||
'allowassign' => $data->allowassign,
|
||||
'allowoverride' => $data->allowoverride,
|
||||
'allowswitch' => $data->allowswitch,
|
||||
'allowview' => $data->allowview);
|
||||
'allowswitch' => $data->allowswitch);
|
||||
if ($showadvanced) {
|
||||
$definitiontable = new core_role_define_role_table_advanced($systemcontext, $roleid);
|
||||
} else {
|
||||
|
||||
@@ -29,7 +29,6 @@ $toprow[] = new tabobject('manage', new moodle_url('/admin/roles/manage.php'), g
|
||||
$toprow[] = new tabobject('assign', new moodle_url('/admin/roles/allow.php', array('mode'=>'assign')), get_string('allowassign', 'core_role'));
|
||||
$toprow[] = new tabobject('override', new moodle_url('/admin/roles/allow.php', array('mode'=>'override')), get_string('allowoverride', 'core_role'));
|
||||
$toprow[] = new tabobject('switch', new moodle_url('/admin/roles/allow.php', array('mode'=>'switch')), get_string('allowswitch', 'core_role'));
|
||||
$toprow[] = new tabobject('view', new moodle_url('/admin/roles/allow.php', ['mode' => 'view']), get_string('allowview', 'core_role'));
|
||||
|
||||
echo $OUTPUT->tabtree($toprow, $currenttab);
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
<xs:element ref="allowassign" minOccurs="0"/>
|
||||
<xs:element ref="allowoverride" minOccurs="0"/>
|
||||
<xs:element ref="allowswitch" minOccurs="0"/>
|
||||
<xs:element ref="allowview" minOccurs="0"/>
|
||||
<xs:element ref="permissions" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
@@ -46,13 +45,6 @@
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="allowview">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element maxOccurs="unbounded" minOccurs="0" ref="shortname"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="permissions">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
|
||||
@@ -44,7 +44,7 @@ class core_role_preset_testcase extends advanced_testcase {
|
||||
$contextlevels = get_role_contextlevels($role->id);
|
||||
$this->assertEquals(array_values($contextlevels), array_values($info['contextlevels']));
|
||||
|
||||
foreach (array('assign', 'override', 'switch', 'view') as $type) {
|
||||
foreach (array('assign', 'override', 'switch') as $type) {
|
||||
$records = $DB->get_records('role_allow_'.$type, array('roleid'=>$role->id), "allow$type ASC");
|
||||
$allows = array();
|
||||
foreach ($records as $record) {
|
||||
|
||||
@@ -1,477 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* Privacy 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;
|
||||
}
|
||||
}
|
||||
+12
-60
@@ -35,7 +35,10 @@ try {
|
||||
// Continue, we return an error later depending on the requested action.
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if ($action) {
|
||||
require_sesskey();
|
||||
|
||||
if ($areaid) {
|
||||
// We need to check that the area exists.
|
||||
@@ -45,76 +48,45 @@ if ($action) {
|
||||
}
|
||||
}
|
||||
|
||||
// All actions but enable/disable need the search engine to be ready.
|
||||
if ($action !== 'enable' && $action !== 'disable') {
|
||||
// All actions but enable/disable need the search engine to be ready.
|
||||
if (!empty($searchmanagererror)) {
|
||||
throw $searchmanagererror;
|
||||
}
|
||||
|
||||
// Show confirm prompt for all these actions as they may be inadvisable, or may cause
|
||||
// an interruption in search functionality, on production systems.
|
||||
if (!optional_param('confirm', 0, PARAM_INT)) {
|
||||
// Display confirmation prompt.
|
||||
$a = null;
|
||||
if ($areaid) {
|
||||
$a = html_writer::tag('strong', $area->get_visible_name());
|
||||
}
|
||||
|
||||
$actionparams = ['sesskey' => sesskey(), 'action' => $action, 'confirm' => 1];
|
||||
if ($areaid) {
|
||||
$actionparams['areaid'] = $areaid;
|
||||
}
|
||||
$actionurl = new moodle_url('/admin/searchareas.php', $actionparams);
|
||||
$cancelurl = new moodle_url('/admin/searchareas.php');
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->confirm(get_string('confirm_' . $action, 'search', $a),
|
||||
new single_button($actionurl, get_string('continue'), 'post', true),
|
||||
new single_button($cancelurl, get_string('cancel'), 'get'));
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// We are now taking an actual action, so require sesskey.
|
||||
require_sesskey();
|
||||
|
||||
switch ($action) {
|
||||
case 'enable':
|
||||
$area->set_enabled(true);
|
||||
\core\notification::add(get_string('searchareaenabled', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
echo $OUTPUT->notification(get_string('searchareaenabled', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'disable':
|
||||
$area->set_enabled(false);
|
||||
\core\notification::add(get_string('searchareadisabled', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
echo $OUTPUT->notification(get_string('searchareadisabled', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'delete':
|
||||
$search = \core_search\manager::instance();
|
||||
$search->delete_index($areaid);
|
||||
\core\notification::add(get_string('searchindexdeleted', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
echo $OUTPUT->notification(get_string('searchindexdeleted', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'indexall':
|
||||
$searchmanager->index();
|
||||
\core\notification::add(get_string('searchindexupdated', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
echo $OUTPUT->notification(get_string('searchindexupdated', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'reindexall':
|
||||
$searchmanager->index(true);
|
||||
\core\notification::add(get_string('searchreindexed', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
echo $OUTPUT->notification(get_string('searchreindexed', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'deleteall':
|
||||
$searchmanager->delete_index();
|
||||
\core\notification::add(get_string('searchalldeleted', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
echo $OUTPUT->notification(get_string('searchalldeleted', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
throw new moodle_exception('invalidaction');
|
||||
break;
|
||||
}
|
||||
|
||||
// Redirect back to the main page after taking action.
|
||||
redirect(new moodle_url('/admin/searchareas.php'));
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$searchareas = \core_search\manager::get_search_areas_list();
|
||||
if (empty($searchmanagererror)) {
|
||||
$areasconfig = $searchmanager->get_areas_config($searchareas);
|
||||
@@ -160,17 +132,7 @@ foreach ($searchareas as $area) {
|
||||
$laststatus = '';
|
||||
}
|
||||
$columns[] = $laststatus;
|
||||
$accesshide = html_writer::span($area->get_visible_name(), 'accesshide');
|
||||
$actions = [];
|
||||
$actions[] = $OUTPUT->pix_icon('t/delete', '') .
|
||||
html_writer::link(admin_searcharea_action_url('delete', $areaid),
|
||||
get_string('deleteindex', 'search', $accesshide));
|
||||
if ($area->supports_get_document_recordset()) {
|
||||
$actions[] = $OUTPUT->pix_icon('i/reload', '') . html_writer::link(
|
||||
new moodle_url('searchreindex.php', ['areaid' => $areaid]),
|
||||
get_string('gradualreindex', 'search', $accesshide));
|
||||
}
|
||||
$columns[] = html_writer::alist($actions, ['class' => 'unstyled list-unstyled']);
|
||||
$columns[] = html_writer::link(admin_searcharea_action_url('delete', $areaid), 'Delete index');
|
||||
|
||||
} else {
|
||||
$blankrow = new html_table_cell(get_string('searchnotavailable', 'admin'));
|
||||
@@ -203,13 +165,6 @@ echo $OUTPUT->single_button(admin_searcharea_action_url('deleteall'), get_string
|
||||
echo $OUTPUT->box_end();
|
||||
|
||||
echo html_writer::table($table);
|
||||
|
||||
if (empty($searchmanagererror)) {
|
||||
// Show information about queued index requests for specific contexts.
|
||||
$searchrenderer = $PAGE->get_renderer('core_search');
|
||||
echo $searchrenderer->render_index_requests_info($searchmanager->get_index_requests_info());
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
/**
|
||||
@@ -220,12 +175,9 @@ echo $OUTPUT->footer();
|
||||
* @return moodle_url
|
||||
*/
|
||||
function admin_searcharea_action_url($action, $areaid = false) {
|
||||
$params = array('action' => $action);
|
||||
$params = array('action' => $action, 'sesskey' => sesskey());
|
||||
if ($areaid) {
|
||||
$params['areaid'] = $areaid;
|
||||
}
|
||||
if ($action === 'disable' || $action === 'enable') {
|
||||
$params['sesskey'] = sesskey();
|
||||
}
|
||||
return new moodle_url('/admin/searchareas.php', $params);
|
||||
}
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Adds a search area to the queue for indexing.
|
||||
*
|
||||
* @package core_search
|
||||
* @copyright 2017 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
require(__DIR__ . '/../config.php');
|
||||
|
||||
// Check access.
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
admin_externalpage_setup('searchareas', '', null, (new moodle_url('/admin/searchreindex.php'))->out(false));
|
||||
|
||||
// Get area parameter and check it exists.
|
||||
$areaid = required_param('areaid', PARAM_ALPHAEXT);
|
||||
$area = \core_search\manager::get_search_area($areaid);
|
||||
if ($area === false) {
|
||||
throw new moodle_exception('invalidrequest');
|
||||
}
|
||||
$areaname = $area->get_visible_name();
|
||||
|
||||
// Start page output.
|
||||
$heading = get_string('gradualreindex', 'search', '');
|
||||
$PAGE->set_title($PAGE->title . ': ' . $heading);
|
||||
$PAGE->navbar->add($heading);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($heading);
|
||||
|
||||
// If sesskey is supplied, actually carry out the action.
|
||||
if (optional_param('sesskey', '', PARAM_ALPHANUM)) {
|
||||
require_sesskey();
|
||||
|
||||
// Get all contexts for search area. This query can take time in large cases.
|
||||
\core_php_time_limit::raise(0);
|
||||
$contextiterator = $area->get_contexts_to_reindex();
|
||||
|
||||
$progress = new \core\progress\display_if_slow('');
|
||||
$progress->start_progress($areaname);
|
||||
|
||||
// Request reindexing for each context (with low priority).
|
||||
$count = 0;
|
||||
foreach ($contextiterator as $context) {
|
||||
\core_php_time_limit::raise(30);
|
||||
\core_search\manager::request_index($context, $area->get_area_id(),
|
||||
\core_search\manager::INDEX_PRIORITY_REINDEXING);
|
||||
$progress->progress();
|
||||
$count++;
|
||||
}
|
||||
|
||||
// Unset the iterator which should close the recordset (if there is one).
|
||||
unset($contextiterator);
|
||||
|
||||
$progress->end_progress();
|
||||
|
||||
$a = (object)['name' => html_writer::tag('strong', $areaname), 'count' => $count];
|
||||
echo $OUTPUT->box(get_string('gradualreindex_queued', 'search', $a));
|
||||
|
||||
echo $OUTPUT->continue_button(new moodle_url('/admin/searchareas.php'));
|
||||
} else {
|
||||
// Display confirmation prompt.
|
||||
echo $OUTPUT->confirm(get_string('gradualreindex_confirm', 'search', html_writer::tag('strong', $areaname)),
|
||||
new single_button(new moodle_url('/admin/searchreindex.php', ['areaid' => $areaid,
|
||||
'sesskey' => sesskey()]), get_string('continue'), 'post', true),
|
||||
new single_button(new moodle_url('/admin/searchareas.php'), get_string('cancel'), 'get'));
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -22,7 +22,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
|
||||
$temp->add(new admin_setting_configcheckbox('allowuserthemes', new lang_string('allowuserthemes', 'admin'), new lang_string('configallowuserthemes', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowcoursethemes', new lang_string('allowcoursethemes', 'admin'), new lang_string('configallowcoursethemes', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowcategorythemes', new lang_string('allowcategorythemes', 'admin'), new lang_string('configallowcategorythemes', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowcohortthemes', new lang_string('allowcohortthemes', 'admin'), new lang_string('configallowcohortthemes', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowthemechangeonurl', new lang_string('allowthemechangeonurl', 'admin'), new lang_string('configallowthemechangeonurl', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowuserblockhiding', new lang_string('allowuserblockhiding', 'admin'), new lang_string('configallowuserblockhiding', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('allowblockstodock', new lang_string('allowblockstodock', 'admin'), new lang_string('configallowblockstodock', 'admin'), 1));
|
||||
@@ -200,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'), 'https://docs.moodle.org', PARAM_URL));
|
||||
$temp->add(new admin_setting_configtext('docroot', new lang_string('docroot', 'admin'), new lang_string('configdocroot', 'admin'), 'http://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));
|
||||
|
||||
@@ -14,11 +14,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('dndallowtextandlinks', new lang_string('dndallowtextandlinks', 'admin'), new lang_string('configdndallowtextandlinks', 'admin'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configexecutable('pathtosassc', new lang_string('pathtosassc', 'admin'), new lang_string('pathtosassc_help', 'admin'), ''));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('forceclean', new lang_string('forceclean', 'core_admin'),
|
||||
new lang_string('forceclean_desc', 'core_admin'), 0));
|
||||
|
||||
$ADMIN->add('experimental', $temp);
|
||||
|
||||
// "debugging" settingpage
|
||||
@@ -33,9 +28,7 @@ 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('tideways_xhprof');
|
||||
$xhprofenabled = $xhprofenabled || extension_loaded('tideways');
|
||||
$xhprofenabled = $xhprofenabled || extension_loaded('xhprof');
|
||||
$xhprofenabled = extension_loaded('xhprof') || extension_loaded('tideways');
|
||||
$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));
|
||||
|
||||
@@ -42,9 +42,6 @@ if (has_capability('moodle/grade:manage', $systemcontext)
|
||||
// enable publishing in exports/imports
|
||||
$temp->add(new admin_setting_configcheckbox('gradepublishing', new lang_string('gradepublishing', 'grades'), new lang_string('gradepublishing_help', 'grades'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('grade_export_exportfeedback', new lang_string('exportfeedback', 'grades'),
|
||||
new lang_string('exportfeedback_desc', 'grades'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configselect('grade_export_displaytype', new lang_string('gradeexportdisplaytype', 'grades'),
|
||||
new lang_string('gradeexportdisplaytype_desc', 'grades'), GRADE_DISPLAY_TYPE_REAL, $display_types));
|
||||
|
||||
|
||||
@@ -556,7 +556,7 @@ if ($hassiteconfig) {
|
||||
// Search engine selection.
|
||||
$temp->add(new admin_setting_heading('searchengineheading', new lang_string('searchengine', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configselect('searchengine',
|
||||
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines));
|
||||
new lang_string('selectsearchengine', 'admin'), '', 'solr', $engines));
|
||||
$temp->add(new admin_setting_heading('searchoptionsheading', new lang_string('searchoptions', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configcheckbox('searchindexwhendisabled',
|
||||
new lang_string('searchindexwhendisabled', 'admin'), new lang_string('searchindexwhendisabled_desc', 'admin'),
|
||||
|
||||
@@ -54,7 +54,8 @@ 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'));
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
$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)
|
||||
@@ -29,7 +28,7 @@ if ($hassiteconfig
|
||||
$choices['1'] = new lang_string('emaildisplayyes');
|
||||
$choices['2'] = new lang_string('emaildisplaycourse');
|
||||
$temp->add(new admin_setting_configselect('defaultpreference_maildisplay', new lang_string('emaildisplay'),
|
||||
new lang_string('emaildisplay_help'), 2, $choices));
|
||||
'', 2, $choices));
|
||||
|
||||
$choices = array();
|
||||
$choices['0'] = new lang_string('textformat');
|
||||
@@ -151,7 +150,6 @@ if ($hassiteconfig
|
||||
$temp->add(new admin_setting_configmultiselect('hiddenuserfields', new lang_string('hiddenuserfields', 'admin'),
|
||||
new lang_string('confighiddenuserfields', 'admin'), array(),
|
||||
array('description' => new lang_string('description'),
|
||||
'email' => new lang_string('email'),
|
||||
'city' => new lang_string('city'),
|
||||
'country' => new lang_string('country'),
|
||||
'timezone' => new lang_string('timezone'),
|
||||
@@ -211,48 +209,3 @@ 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);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
@core @core_admin
|
||||
Feature: Use the search areas admin screen
|
||||
In order to control search indexing
|
||||
As an admin
|
||||
I need to use the search areas admin screen
|
||||
|
||||
Background:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Plugins > Search > Search areas" in site administration
|
||||
|
||||
Scenario: Disable and enable a search area
|
||||
When I click on "Disable" "link" in the "Book - resource information" "table_row"
|
||||
Then I should see "Search area disabled" in the ".alert-success" "css_element"
|
||||
And I should see "Search area disabled" in the "Book - resource information" "table_row"
|
||||
|
||||
When I click on "Enable" "link" in the "Book - resource information" "table_row"
|
||||
Then I should see "Search area enabled" in the ".alert-success" "css_element"
|
||||
And I should not see "Search area disabled" in the "Book - resource information" "table_row"
|
||||
|
||||
# Note: Other scenarios are not currently easy to implement in Behat because there is no mock
|
||||
# search engine - we could add testing once Moodle has an internal database search engine.
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Helper class that contains helper functions for cli scripts.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 onwards Ankit Agarwal
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Helper class that contains helper functions for cli scripts.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 onwards Ankit Agarwal
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class clihelper {
|
||||
|
||||
/**
|
||||
* List all models in the system. To be used from cli scripts.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function list_models() {
|
||||
cli_heading("List of models");
|
||||
echo str_pad(get_string('modelid', 'tool_analytics'), 15, ' ') . ' ' . str_pad(get_string('name'), 50, ' ') .
|
||||
' ' . str_pad(get_string('status'), 15, ' ') . "\n";
|
||||
$models = \core_analytics\manager::get_all_models();
|
||||
foreach ($models as $model) {
|
||||
$modelid = $model->get_id();
|
||||
$isenabled = $model->is_enabled() ? get_string('enabled', 'tool_analytics') : get_string('disabled', 'tool_analytics');
|
||||
$name = $model->get_target()->get_name();
|
||||
echo str_pad($modelid, 15, ' ') . ' ' . str_pad($name, 50, ' ') . ' ' . str_pad($isenabled, 15, ' ') . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_analytics.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_analytics 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() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ $help = "Enables the provided model.
|
||||
|
||||
Options:
|
||||
--modelid Model id
|
||||
--list List models
|
||||
--timesplitting Time splitting method full class name
|
||||
-h, --help Print out this help
|
||||
|
||||
@@ -43,7 +42,6 @@ Example:
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
array(
|
||||
'help' => false,
|
||||
'list' => false,
|
||||
'modelid' => false,
|
||||
'timesplitting' => false
|
||||
),
|
||||
@@ -57,12 +55,7 @@ if ($options['help']) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['list'] || $options['modelid'] === false) {
|
||||
\tool_analytics\clihelper::list_models();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['timesplitting'] === false) {
|
||||
if ($options['modelid'] === false || $options['timesplitting'] === false) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ $help = "Evaluates the provided model.
|
||||
|
||||
Options:
|
||||
--modelid Model id
|
||||
--list List models
|
||||
--non-interactive Not interactive questions
|
||||
--timesplitting Restrict the evaluation to 1 single time splitting method (Optional)
|
||||
--filter Analyser dependant. e.g. A courseid would evaluate the model using a single course (Optional)
|
||||
@@ -48,7 +47,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
array(
|
||||
'help' => false,
|
||||
'modelid' => false,
|
||||
'list' => false,
|
||||
'timesplitting' => false,
|
||||
'reuse-prev-analysed' => true,
|
||||
'non-interactive' => false,
|
||||
@@ -64,8 +62,8 @@ if ($options['help']) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['list'] || $options['modelid'] === false) {
|
||||
\tool_analytics\clihelper::list_models();
|
||||
if ($options['modelid'] === false) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ $string['clearmodelpredictions'] = 'Are you sure you want to clear all "{$a}" pr
|
||||
$string['clienablemodel'] = 'You can enable the model by selecting a time-splitting method by its ID. Note that you can also enable it later using the web interface (\'none\' to exit).';
|
||||
$string['clievaluationandpredictions'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. You can allow these processes to be executed manually via the web interface by disabling the <a href="{$a}">\'onlycli\'</a> analytics setting.';
|
||||
$string['clievaluationandpredictionsnoadmin'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. It may be enabled by a site administrator.';
|
||||
$string['disabled'] = 'Disabled';
|
||||
$string['editmodel'] = 'Edit "{$a}" model';
|
||||
$string['edittrainedwarning'] = 'This model has already been trained. Note that changing its indicators or its time-splitting method will delete its previous predictions and start generating new predictions.';
|
||||
$string['enabled'] = 'Enabled';
|
||||
@@ -67,7 +66,6 @@ $string['invalidanalysablestable'] = 'Invalid site analysable elements table';
|
||||
$string['invalidprediction'] = 'Invalid to get predictions';
|
||||
$string['invalidtraining'] = 'Invalid to train the model';
|
||||
$string['loginfo'] = 'Log extra info';
|
||||
$string['modelid'] = 'Model ID';
|
||||
$string['modelinvalidanalysables'] = 'Invalid analysable elements for "{$a}" model';
|
||||
$string['modelresults'] = '{$a} results';
|
||||
$string['modeltimesplitting'] = 'Time splitting';
|
||||
@@ -94,4 +92,3 @@ $string['trainmodels'] = 'Train models';
|
||||
$string['viewlog'] = 'Log';
|
||||
$string['weeksenddateautomaticallyset'] = 'End date automatically set based on start date and the number of sections';
|
||||
$string['weeksenddatedefault'] = 'End date automatically calculated from the course start date.';
|
||||
$string['privacy:metadata'] = 'The Analytic models plugin does not store any personal data.';
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2018050800; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for 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 {
|
||||
$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(int $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,4 +58,3 @@ $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.';
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2018051400;
|
||||
$plugin->requires = 2018050800;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_assignmentupgrade';
|
||||
$plugin->dependencies = array('mod_assign' => 2018050800);
|
||||
$plugin->dependencies = array('mod_assign' => 2017110800);
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for 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() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,3 @@
|
||||
|
||||
$string['manageplugins'] = 'Manage restrictions';
|
||||
$string['pluginname'] = 'Availability condition management';
|
||||
$string['privacy:metadata'] = 'The Availability condition management plugin does not store any personal data.';
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2018051400;
|
||||
$plugin->requires = 2018050800;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_availabilityconditions';
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for 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() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -50,4 +50,3 @@ $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.';
|
||||
|
||||
@@ -139,7 +139,7 @@ class tool_behat_renderer extends plugin_renderer_base {
|
||||
$msg = get_string('wrongbehatsetup', 'tool_behat', $a);
|
||||
|
||||
// Error box including generic error string + specific error msg.
|
||||
$html .= $this->output->box_start('box errorbox alert alert-danger');
|
||||
$html .= $this->output->box_start('box errorbox');
|
||||
$html .= html_writer::tag('div', $msg);
|
||||
$html .= $this->output->box_end();
|
||||
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2018050800; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for 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() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -34,4 +34,3 @@ $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.';
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2018050800; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -167,7 +167,7 @@ class api {
|
||||
$params['roleid'] = $roleid;
|
||||
$params['userid'] = $userid;
|
||||
|
||||
$sql = 'SELECT DISTINCT u.id AS userid, ra.id, ctx.id AS contextid
|
||||
$sql = 'SELECT 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
|
||||
|
||||
@@ -94,12 +94,11 @@ class cohort_role_assignments_table extends table_sql {
|
||||
'idnumber' => $data->cohortidnumber,
|
||||
'description' => $data->cohortdescription,
|
||||
'visible' => $data->cohortvisible,
|
||||
'name' => $data->cohortname,
|
||||
'theme' => $data->cohorttheme
|
||||
'name' => $data->cohortname
|
||||
);
|
||||
$context = context_helper::instance_by_id($data->cohortcontextid);
|
||||
|
||||
$exporter = new \core_cohort\external\cohort_summary_exporter($record, array('context' => $context));
|
||||
$exporter = new \tool_lp\external\cohort_summary_exporter($record, array('context' => $context));
|
||||
$cohort = $exporter->export($OUTPUT);
|
||||
|
||||
$html = $OUTPUT->render_from_template('tool_cohortroles/cohort-in-list', $cohort);
|
||||
@@ -170,7 +169,7 @@ class cohort_role_assignments_table extends table_sql {
|
||||
protected function get_sql_and_params($count = false) {
|
||||
$fields = 'uca.id, uca.cohortid, uca.userid, uca.roleid, ';
|
||||
$fields .= 'c.name as cohortname, c.idnumber as cohortidnumber, c.contextid as cohortcontextid, ';
|
||||
$fields .= 'c.visible as cohortvisible, c.description as cohortdescription, c.theme as cohorttheme, ';
|
||||
$fields .= 'c.visible as cohortvisible, c.description as cohortdescription, ';
|
||||
|
||||
// Add extra user fields that we need for the graded user.
|
||||
$extrafields = get_extra_user_fields($this->context);
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for 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) : 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(int $userid) : contextlist {
|
||||
$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,11 +42,3 @@ $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.';
|
||||
|
||||
@@ -31,15 +31,13 @@
|
||||
* idnumber cohort idnumber field
|
||||
* description cohort description field
|
||||
* visible cohort visible field
|
||||
* theme cohort theme field
|
||||
|
||||
Example context (json):
|
||||
{ "id": "1",
|
||||
"name": "Cohort 1",
|
||||
"visible": true,
|
||||
"idnumber": "014",
|
||||
"description": "Some users",
|
||||
"theme": "clean"
|
||||
"description": "Some users"
|
||||
}
|
||||
}}
|
||||
{{> tool_lp/form-cohort-selector-suggestion }}
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,8 +25,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2018051400; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2018050800; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_cohortroles'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
$plugin->dependencies = array(
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for 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() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,9 @@ defined('MOODLE_INTERNAL') || die();
|
||||
function xmldb_tool_customlang_upgrade($oldversion) {
|
||||
global $CFG;
|
||||
|
||||
// Moodle v3.1.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.2.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
|
||||
@@ -59,4 +59,3 @@ $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.';
|
||||
|
||||
@@ -159,11 +159,6 @@ 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) {
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2018051400;
|
||||
$plugin->requires = 2018050800;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_customlang'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/str","core/ajax","core/notification","core/modal_factory","core/modal_events","core/fragment"],function(a,b,c,d,e,f,g){var h={CATEGORY_LINK:'[data-add-element="category"]'},i=function(a){this.contextId=a;var c=[{key:"addcategory",component:"tool_dataprivacy"},{key:"save",component:"admin"}];this.strings=b.get_strings(c),this.registerEventListeners()};return i.prototype.contextId=0,i.prototype.strings=0,i.prototype.registerEventListeners=function(){var b=a(h.CATEGORY_LINK);b.on("click",function(){return this.strings.then(function(a){e.create({type:e.types.SAVE_CANCEL,title:a[0],body:""},b).done(function(b){this.setupFormModal(b,a[1])}.bind(this))}.bind(this)).fail(d.exception)}.bind(this))},i.prototype.getBody=function(a){var b=null;return"undefined"!=typeof a&&(b={jsonformdata:JSON.stringify(a)}),g.loadFragment("tool_dataprivacy","addcategory_form",this.contextId,b)},i.prototype.setupFormModal=function(a,b){a.setLarge(),a.setSaveButtonText(b),a.getRoot().on(f.hidden,this.destroy.bind(this)),a.setBody(this.getBody()),a.getRoot().on(f.save,this.submitForm.bind(this)),a.getRoot().on("submit","form",this.submitFormAjax.bind(this)),this.modal=a,a.show()},i.prototype.submitForm=function(a){a.preventDefault(),this.modal.getRoot().find("form").submit()},i.prototype.submitFormAjax=function(a){a.preventDefault();var b=this.modal.getRoot().find("form").serialize();c.call([{methodname:"tool_dataprivacy_create_category_form",args:{jsonformdata:JSON.stringify(b)},done:function(a){a.validationerrors?this.modal.setBody(this.getBody(b)):this.close()}.bind(this),fail:d.exception}])},i.prototype.close=function(){this.destroy(),document.location.reload()},i.prototype.destroy=function(){Y.use("moodle-core-formchangechecker",function(){M.core_formchangechecker.reset_form_dirty_state()}),this.modal.destroy()},i.prototype.removeListeners=function(){a(h.CATEGORY_LINK).off("click")},{getInstance:function(a){return new i(a)}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/str","core/ajax","core/notification","core/modal_factory","core/modal_events","core/fragment"],function(a,b,c,d,e,f,g){var h={PURPOSE_LINK:'[data-add-element="purpose"]'},i=function(a){this.contextId=a;var c=[{key:"addpurpose",component:"tool_dataprivacy"},{key:"save",component:"admin"}];this.strings=b.get_strings(c),this.registerEventListeners()};return i.prototype.contextId=0,i.prototype.strings=0,i.prototype.registerEventListeners=function(){var b=a(h.PURPOSE_LINK);b.on("click",function(){return this.strings.then(function(a){e.create({type:e.types.SAVE_CANCEL,title:a[0],body:""},b).done(function(b){this.setupFormModal(b,a[1])}.bind(this))}.bind(this)).fail(d.exception)}.bind(this))},i.prototype.getBody=function(a){var b=null;return"undefined"!=typeof a&&(b={jsonformdata:JSON.stringify(a)}),g.loadFragment("tool_dataprivacy","addpurpose_form",this.contextId,b)},i.prototype.setupFormModal=function(a,b){a.setLarge(),a.setSaveButtonText(b),a.getRoot().on(f.hidden,this.destroy.bind(this)),a.setBody(this.getBody()),a.getRoot().on(f.save,this.submitForm.bind(this)),a.getRoot().on("submit","form",this.submitFormAjax.bind(this)),this.modal=a,a.show()},i.prototype.submitForm=function(a){a.preventDefault(),this.modal.getRoot().find("form").submit()},i.prototype.submitFormAjax=function(a){a.preventDefault();var b=this.modal.getRoot().find("form").serialize();c.call([{methodname:"tool_dataprivacy_create_purpose_form",args:{jsonformdata:JSON.stringify(b)},done:function(a){a.validationerrors?this.modal.setBody(this.getBody(b)):this.close()}.bind(this),fail:d.exception}])},i.prototype.close=function(){this.destroy(),document.location.reload()},i.prototype.destroy=function(){Y.use("moodle-core-formchangechecker",function(){M.core_formchangechecker.reset_form_dirty_state()}),this.modal.destroy()},i.prototype.removeListeners=function(){a(h.PURPOSE_LINK).off("click")},{getInstance:function(a){return new i(a)}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){var g={DELETE:'[data-action="deletecategory"]'},h=function(){this.registerEvents()};return h.prototype.registerEvents=function(){a(g.DELETE).click(function(g){g.preventDefault();var h=a(this).data("id"),i=a(this).data("name"),j=[{key:"deletecategory",component:"tool_dataprivacy",param:i},{key:"deletecategorytext",component:"tool_dataprivacy",param:i}];d.get_strings(j).then(function(d){var g=d[0],i=d[1];return e.create({title:g,body:i,type:e.types.SAVE_CANCEL}).then(function(d){return d.setSaveButtonText(g),d.getRoot().on(f.save,function(){var d={methodname:"tool_dataprivacy_delete_category",args:{id:h}};b.call([d])[0].done(function(b){b.result?a('tr[data-categoryid="'+h+'"]').remove():c.addNotification({message:b.warnings[0].message,type:"error"})}).fail(c.exception)}),d.getRoot().on(f.hidden,function(){d.destroy()}),d})}).done(function(a){a.show()}).fail(c.exception)})},{init:function(){return new h}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){function g(a){var g=[{key:"confirm",component:"moodle"},{key:"confirmcontextdeletion",component:"tool_dataprivacy"}],h="tool_dataprivacy_confirm_contexts_for_deletion",i="";d.get_strings(g).then(function(a){i=a[0];var b=a[1];return e.create({title:i,body:b,type:e.types.SAVE_CANCEL})}).then(function(d){return d.setSaveButtonText(i),d.getRoot().on(f.save,function(){var d={ids:a},e={methodname:h,args:d};b.call([e])[0].done(function(a){a.result?window.location.reload():c.addNotification({message:a.warnings[0].message,type:"error"})}).fail(c.exception)}),d.getRoot().on(f.hidden,function(){d.destroy()}),d}).done(function(a){a.show()}).fail(c.exception)}var h={MARK_FOR_DELETION:'[data-action="markfordeletion"]',SELECT_ALL:'[data-action="selectall"]'},i={SELECTCONTEXT:".selectcontext"},j=function(){this.registerEvents()};return j.prototype.registerEvents=function(){a(h.MARK_FOR_DELETION).click(function(b){b.preventDefault();var c=[];a(i.SELECTCONTEXT).each(function(){var b=a(this);b.is(":checked")&&c.push(b.val())}),g(c)}),a(h.SELECT_ALL).change(function(b){b.preventDefault();var c=a(this);c.is(":checked")?a(i.SELECTCONTEXT).attr("checked","checked"):a(i.SELECTCONTEXT).removeAttr("checked")})},j});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/str","core/ajax","core/notification","core/templates","core/modal_factory","core/modal_events","core/fragment","tool_dataprivacy/add_purpose","tool_dataprivacy/add_category"],function(a,b,c,d,e,f,g,h,i,j){var k={TREE_NODES:"[data-context-tree-node=1]",FORM_CONTAINER:"#context-form-container"},l=function(a,b,c){this.systemContextId=a,this.currentContextLevel=b,this.currentContextId=c,this.init()};return l.prototype.systemContextId=0,l.prototype.currentContextLevel=0,l.prototype.currentContextId=0,l.prototype.addpurpose=null,l.prototype.addcategory=null,l.prototype.init=function(){this.addpurpose=i.getInstance(this.systemContextId),this.addcategory=j.getInstance(this.systemContextId);var a=[{key:"changessaved",component:"moodle"},{key:"contextpurposecategorysaved",component:"tool_dataprivacy"},{key:"noblockstoload",component:"tool_dataprivacy"},{key:"noactivitiestoload",component:"tool_dataprivacy"},{key:"nocoursestoload",component:"tool_dataprivacy"}];this.strings=b.get_strings(a),this.registerEventListeners(),this.currentContextId?this.loadForm("context_form",[this.currentContextId],this.submitContextFormAjax.bind(this)):this.loadForm("contextlevel_form",[this.currentContextLevel],this.submitContextLevelFormAjax.bind(this))},l.prototype.registerEventListeners=function(){a(k.TREE_NODES).on("click",function(b){b.preventDefault();var c=a(b.currentTarget);a(k.TREE_NODES).removeClass("active"),c.addClass("active");var d=c.data("contextlevel"),e=c.data("contextid");if(d)window.history.pushState({},null,"?contextlevel="+d),this.addpurpose.removeListeners(),this.addcategory.removeListeners(),this.currentContextLevel=d,this.loadForm("contextlevel_form",[this.currentContextLevel],this.submitContextLevelFormAjax.bind(this));else if(e)window.history.pushState({},null,"?contextid="+e),this.addpurpose.removeListeners(),this.addcategory.removeListeners(),this.currentContextId=e,this.loadForm("context_form",[this.currentContextId],this.submitContextFormAjax.bind(this));else{var f=c.data("expandcontextid"),g=c.data("expandelement"),h=c.data("expanded");g&&(h?this.collapse(c):!c.data("loaded")&&f&&g?(c.find("> i").removeClass("fa-plus"),c.find("> i").addClass("fa-circle-o-notch fa-spin"),this.loadExtra(c,f,g)):this.expand(c))}}.bind(this))},l.prototype.removeListeners=function(){a(k.TREE_NODES).off("click")},l.prototype.loadForm=function(b,c,f){this.clearForm();var g=h.loadFragment("tool_dataprivacy",b,this.systemContextId,c);g.done(function(b,c){a(k.FORM_CONTAINER).html(b),e.runTemplateJS(c),this.addpurpose.registerEventListeners(),this.addcategory.registerEventListeners(),a(k.FORM_CONTAINER).on("submit","form",f)}.bind(this)).fail(d.exception)},l.prototype.clearForm=function(){Y.use("moodle-core-formchangechecker",function(){M.core_formchangechecker.reset_form_dirty_state()}),a(k.FORM_CONTAINER).off("submit","form")},l.prototype.submitForm=function(b){b.preventDefault(),a(k.FORM_CONTAINER).find("form").submit()},l.prototype.submitContextLevelFormAjax=function(a){this.submitFormAjax(a,"tool_dataprivacy_set_contextlevel_form")},l.prototype.submitContextFormAjax=function(a){this.submitFormAjax(a,"tool_dataprivacy_set_context_form")},l.prototype.submitFormAjax=function(b,e){b.preventDefault();var f=a(k.FORM_CONTAINER).find("form").serialize();return this.strings.then(function(a){c.call([{methodname:e,args:{jsonformdata:JSON.stringify(f)},done:function(){d.alert(a[0],a[1])},fail:d.exception}])})["catch"](d.exception)},l.prototype.loadExtra=function(a,b,f){c.call([{methodname:"tool_dataprivacy_tree_extra_branches",args:{contextid:b,element:f},done:function(b){return 0==b.branches.length?void this.noElements(a,f):void e.render("tool_dataprivacy/context_tree_branches",b).then(function(b){a.after(b),this.removeListeners(),this.registerEventListeners(),this.expand(a),a.data("loaded",1)}.bind(this)).fail(d.exception)}.bind(this),fail:d.exception}])},l.prototype.noElements=function(a,b){a.data("expandcontextid",""),a.data("expandelement",""),this.strings.then(function(c){var d=2;"module"==b?d=3:"course"==b&&(d=4),a.text(c[d])}).fail(d.exception)},l.prototype.collapse=function(a){a.data("expanded",0),a.siblings("nav").addClass("hidden"),a.find("> i").removeClass("fa-minus"),a.find("> i").addClass("fa-plus")},l.prototype.expand=function(a){a.data("expanded",1),a.siblings("nav").removeClass("hidden"),a.find("> i").removeClass("fa-plus"),a.find("> i").removeClass("fa-circle-o-notch fa-spin"),a.find("> i").addClass("fa-minus")},{init:function(a,b,c){return new l(a,b,c)}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","tool_dataprivacy/events"],function(a,b,c,d,e,f){var g=!1,h={APPROVE_BUTTON:'[data-action="approve"]',DENY_BUTTON:'[data-action="deny"]'},i=function(a){d.call(this,a),this.getFooter().find(h.APPROVE_BUTTON).length||b.exception({message:"No approve button found"}),this.getFooter().find(h.DENY_BUTTON).length||b.exception({message:"No deny button found"})};return i.TYPE="tool_dataprivacy-data_request",i.prototype=Object.create(d.prototype),i.prototype.constructor=i,i.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this),this.getModal().on(c.events.activate,h.APPROVE_BUTTON,function(b,c){var d=a.Event(f.approve);this.getRoot().trigger(d,this),d.isDefaultPrevented()||(this.hide(),c.originalEvent.preventDefault())}.bind(this)),this.getModal().on(c.events.activate,h.DENY_BUTTON,function(b,c){var d=a.Event(f.deny);this.getRoot().trigger(d,this),d.isDefaultPrevented()||(this.hide(),c.originalEvent.preventDefault())}.bind(this))},g||(e.register(i.TYPE,i,"tool_dataprivacy/data_request_modal"),g=!0),i});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery"],function(a){var b={PURPOSE_SELECT:"#id_purposeid",RETENTION_FIELD_BOOST:"#id_error_retention_current",RETENTION_FIELD_CLEAN:"#fitem_id_retention_current [data-fieldtype=static]"},c=function(a){this.purposeRetentionPeriods=a,this.registerEventListeners()},d=function(){a(b.PURPOSE_SELECT).off("change")};return c.prototype.purposeRetentionPeriods=[],c.prototype.registerEventListeners=function(){a(b.PURPOSE_SELECT).on("change",function(c){var d=a(c.currentTarget).val(),e=this.purposeRetentionPeriods[d],f=a(b.RETENTION_FIELD_CLEAN);if(f.length>0)f.text(e);else{var g=a(b.RETENTION_FIELD_BOOST),h=g.siblings();h.length>0&&h.text(e)}}.bind(this))},{init:function(a){return d(),new c(a)}}});
|
||||
@@ -1 +0,0 @@
|
||||
define([],function(){return{approve:"tool_dataprivacy-data_request:approve",deny:"tool_dataprivacy-data_request:deny"}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/url","core/str"],function(a,b,c){var d=a('<img alt="" src="'+b.imageUrl("t/expanded")+'"/>'),e=a('<img alt="" src="'+b.imageUrl("t/collapsed")+'"/>');return{expandCollapse:function(a,b){a.hasClass("hide")?(a.removeClass("hide"),a.addClass("visible"),a.attr("aria-expanded",!0),b.find(":header i.fa").removeClass("fa-plus-square"),b.find(":header i.fa").addClass("fa-minus-square"),b.find(":header img.icon").attr("src",d.attr("src"))):(a.removeClass("visible"),a.addClass("hide"),a.attr("aria-expanded",!1),b.find(":header i.fa").removeClass("fa-minus-square"),b.find(":header i.fa").addClass("fa-plus-square"),b.find(":header img.icon").attr("src",e.attr("src")))},expandCollapseAll:function(b){var f="visible"==b?"hide":"visible",g="visible"==b,h="visible"==b?"fa-plus-square":"fa-minus-square",i="visible"==b?"fa-minus-square":"fa-plus-square",j="visible"==b?d.attr("src"):e.attr("src");a("."+f).each(function(){a(this).removeClass(f),a(this).addClass(b),a(this).attr("aria-expanded",g)}),a(".tool_dataprivacy-expand-all").data("visibilityState",f),c.get_string(f,"tool_dataprivacy").then(function(b){a(".tool_dataprivacy-expand-all").html(b)})["catch"](Notification.exception),a(":header i.fa").each(function(){a(this).removeClass(h),a(this).addClass(i)}),a(":header img.icon").each(function(){a(this).attr("src",j)})}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/templates"],function(a,b,c){return{processResults:function(b,c){var d=[];return a.each(c,function(a,b){d.push({value:b.id,label:b._label})}),d},transport:function(d,e,f,g){var h;h=b.call([{methodname:"tool_dataprivacy_get_users",args:{query:e}}]),h[0].then(function(b){var d=[],e=0;return a.each(b,function(a,b){d.push(c.render("tool_dataprivacy/form-user-selector-suggestion",b))}),a.when.apply(a.when,d).then(function(){var c=arguments;a.each(b,function(a,b){b._label=c[e],e++}),f(b)})}).fail(g)}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events","core/templates"],function(a,b,c,d,e,f,g){function h(a){var e={methodname:"tool_dataprivacy_contact_dpo",args:{message:a}},f="success";b.call([e])[0].then(function(a){return a.result?d.get_string("requestsubmitted","tool_dataprivacy"):(f="error",a.warnings.join("<br>"))}).done(function(a){c.addNotification({message:a,type:f})}).fail(c.exception)}var i={CANCEL_REQUEST:'[data-action="cancel"]',CONTACT_DPO:'[data-action="contactdpo"]'},j=function(){this.registerEvents()};return j.prototype.registerEvents=function(){a(i.CANCEL_REQUEST).click(function(g){g.preventDefault();var h=a(this).data("requestid"),i=[{key:"cancelrequest",component:"tool_dataprivacy"},{key:"cancelrequestconfirmation",component:"tool_dataprivacy"}];d.get_strings(i).then(function(a){var d=a[0],g=a[1];return e.create({title:d,body:g,type:e.types.SAVE_CANCEL}).then(function(a){return a.setSaveButtonText(d),a.getRoot().on(f.save,function(){var a={requestid:h},d={methodname:"tool_dataprivacy_cancel_data_request",args:a};b.call([d])[0].done(function(a){a.result?window.location.reload():c.addNotification({message:a.warnings[0].message,type:"error"})}).fail(c.exception)}),a.getRoot().on(f.hidden,function(){a.destroy()}),a})}).done(function(a){a.show()}).fail(c.exception)}),a(i.CONTACT_DPO).click(function(b){b.preventDefault();var i=a(this).data("replytoemail"),j=[{key:"contactdataprotectionofficer",component:"tool_dataprivacy"},{key:"send",component:"tool_dataprivacy"}],k="";d.get_strings(j).then(function(a){var b=a[0];k=a[1];var c={replytoemail:i};return e.create({title:b,body:g.render("tool_dataprivacy/contact_dpo",c),type:e.types.SAVE_CANCEL,large:!0})}).done(function(b){b.setSaveButtonText(k),b.getRoot().on(f.save,function(b){var c=a("#message").val().trim();0===c.length?(b.preventDefault(),a('[data-region="messageinput"]').addClass("has-danger notifyproblem"),a("#id_error_message").removeAttr("hidden")):h(c)}),b.getRoot().on(f.hidden,function(){b.destroy()}),b.show()}).fail(c.exception)})},{init:function(){return new j}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){var g={DELETE:'[data-action="deletepurpose"]'},h=function(){this.registerEvents()};return h.prototype.registerEvents=function(){a(g.DELETE).click(function(g){g.preventDefault();var h=a(this).data("id"),i=a(this).data("name"),j=[{key:"deletepurpose",component:"tool_dataprivacy",param:i},{key:"deletepurposetext",component:"tool_dataprivacy",param:i}];d.get_strings(j).then(function(d){var g=d[0],i=d[1];return e.create({title:g,body:i,type:e.types.SAVE_CANCEL}).then(function(d){return d.setSaveButtonText(g),d.getRoot().on(f.save,function(){var d={methodname:"tool_dataprivacy_delete_purpose",args:{id:h}};b.call([d])[0].done(function(b){b.result?a('tr[data-purposeid="'+h+'"]').remove():c.addNotification({message:b.warnings[0].message,type:"error"})}).fail(c.exception)}),d.getRoot().on(f.hidden,function(){d.destroy()}),d})}).done(function(a){a.show()}).fail(c.exception)})},{init:function(){return new h}}});
|
||||
@@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events","core/templates","tool_dataprivacy/data_request_modal","tool_dataprivacy/events"],function(a,b,c,d,e,f,g,h,i){function j(a,g){var h=[],j="";switch(a){case i.approve:h=[{key:"approverequest",component:"tool_dataprivacy"},{key:"confirmapproval",component:"tool_dataprivacy"}],j="tool_dataprivacy_approve_data_request";break;case i.deny:h=[{key:"denyrequest",component:"tool_dataprivacy"},{key:"confirmdenial",component:"tool_dataprivacy"}],j="tool_dataprivacy_deny_data_request"}var k="";d.get_strings(h).then(function(a){k=a[0];var b=a[1];return e.create({title:k,body:b,type:e.types.SAVE_CANCEL})}).then(function(a){return a.setSaveButtonText(k),a.getRoot().on(f.save,function(){var a={requestid:g},d={methodname:j,args:a};b.call([d])[0].done(function(a){a.result?window.location.reload():c.addNotification({message:a.warnings[0].message,type:"error"})}).fail(c.exception)}),a.getRoot().on(f.hidden,function(){a.destroy()}),a}).done(function(a){a.show()}).fail(c.exception)}var k={APPROVE_REQUEST:'[data-action="approve"]',DENY_REQUEST:'[data-action="deny"]',VIEW_REQUEST:'[data-action="view"]'},l=function(){this.registerEvents()};return l.prototype.registerEvents=function(){a(k.VIEW_REQUEST).click(function(d){d.preventDefault();var k=a(this).data("requestid"),l={requestid:k},m={methodname:"tool_dataprivacy_get_data_request",args:l},n=b.call([m]),o="",p=e.types.DEFAULT;a.when(n[0]).then(function(a){return a.result?(2==a.result.status&&(p=h.TYPE),o=a.result.typename,g.render("tool_dataprivacy/request_details",a.result)):(c.addNotification({message:a.warnings[0].message,type:"error"}),!1)}).then(function(a){return e.create({title:o,body:a,type:p,large:!0}).then(function(a){return a.getRoot().on(i.approve,function(){j(i.approve,k)}),a.getRoot().on(i.deny,function(){j(i.deny,k)}),a.getRoot().on(f.hidden,function(){a.destroy()}),a})}).done(function(a){a.show()}).fail(c.exception)}),a(k.APPROVE_REQUEST).click(function(b){b.preventDefault();var c=a(this).data("requestid");j(i.approve,c)}),a(k.DENY_REQUEST).click(function(b){b.preventDefault();var c=a(this).data("requestid");j(i.deny,c)})},l});
|
||||
@@ -1,172 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Module to add categories.
|
||||
*
|
||||
* @module tool_dataprivacy/add_category
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/str', 'core/ajax', 'core/notification', 'core/modal_factory', 'core/modal_events', 'core/fragment'],
|
||||
function($, Str, Ajax, Notification, ModalFactory, ModalEvents, Fragment) {
|
||||
|
||||
var SELECTORS = {
|
||||
CATEGORY_LINK: '[data-add-element="category"]',
|
||||
};
|
||||
|
||||
var AddCategory = function(contextId) {
|
||||
this.contextId = contextId;
|
||||
|
||||
var stringKeys = [
|
||||
{
|
||||
key: 'addcategory',
|
||||
component: 'tool_dataprivacy'
|
||||
},
|
||||
{
|
||||
key: 'save',
|
||||
component: 'admin'
|
||||
}
|
||||
];
|
||||
this.strings = Str.get_strings(stringKeys);
|
||||
|
||||
this.registerEventListeners();
|
||||
};
|
||||
|
||||
/**
|
||||
* @var {int} contextId
|
||||
* @private
|
||||
*/
|
||||
AddCategory.prototype.contextId = 0;
|
||||
|
||||
/**
|
||||
* @var {Promise}
|
||||
* @private
|
||||
*/
|
||||
AddCategory.prototype.strings = 0;
|
||||
|
||||
AddCategory.prototype.registerEventListeners = function() {
|
||||
|
||||
var trigger = $(SELECTORS.CATEGORY_LINK);
|
||||
trigger.on('click', function() {
|
||||
return this.strings.then(function(strings) {
|
||||
ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
title: strings[0],
|
||||
body: '',
|
||||
}, trigger).done(function(modal) {
|
||||
this.setupFormModal(modal, strings[1]);
|
||||
}.bind(this));
|
||||
}.bind(this))
|
||||
.fail(Notification.exception);
|
||||
}.bind(this));
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @method getBody
|
||||
* @param {Object} formdata
|
||||
* @private
|
||||
* @return {Promise}
|
||||
*/
|
||||
AddCategory.prototype.getBody = function(formdata) {
|
||||
|
||||
var params = null;
|
||||
if (typeof formdata !== "undefined") {
|
||||
params = {jsonformdata: JSON.stringify(formdata)};
|
||||
}
|
||||
// Get the content of the modal.
|
||||
return Fragment.loadFragment('tool_dataprivacy', 'addcategory_form', this.contextId, params);
|
||||
};
|
||||
|
||||
AddCategory.prototype.setupFormModal = function(modal, saveText) {
|
||||
modal.setLarge();
|
||||
|
||||
modal.setSaveButtonText(saveText);
|
||||
|
||||
// We want to reset the form every time it is opened.
|
||||
modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));
|
||||
|
||||
modal.setBody(this.getBody());
|
||||
|
||||
// We catch the modal save event, and use it to submit the form inside the modal.
|
||||
// Triggering a form submission will give JS validation scripts a chance to check for errors.
|
||||
modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
|
||||
// We also catch the form submit event and use it to submit the form with ajax.
|
||||
modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
|
||||
|
||||
this.modal = modal;
|
||||
|
||||
modal.show();
|
||||
};
|
||||
|
||||
/**
|
||||
* This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
|
||||
*
|
||||
* @method submitForm
|
||||
* @param {Event} e Form submission event.
|
||||
* @private
|
||||
*/
|
||||
AddCategory.prototype.submitForm = function(e) {
|
||||
e.preventDefault();
|
||||
this.modal.getRoot().find('form').submit();
|
||||
};
|
||||
|
||||
AddCategory.prototype.submitFormAjax = function(e) {
|
||||
// We don't want to do a real form submission.
|
||||
e.preventDefault();
|
||||
|
||||
// Convert all the form elements values to a serialised string.
|
||||
var formData = this.modal.getRoot().find('form').serialize();
|
||||
|
||||
Ajax.call([{
|
||||
methodname: 'tool_dataprivacy_create_category_form',
|
||||
args: {jsonformdata: JSON.stringify(formData)},
|
||||
done: function(data) {
|
||||
if (data.validationerrors) {
|
||||
this.modal.setBody(this.getBody(formData));
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}.bind(this),
|
||||
fail: Notification.exception
|
||||
}]);
|
||||
};
|
||||
|
||||
AddCategory.prototype.close = function() {
|
||||
this.destroy();
|
||||
document.location.reload();
|
||||
};
|
||||
|
||||
AddCategory.prototype.destroy = function() {
|
||||
Y.use('moodle-core-formchangechecker', function() {
|
||||
M.core_formchangechecker.reset_form_dirty_state();
|
||||
});
|
||||
this.modal.destroy();
|
||||
};
|
||||
|
||||
AddCategory.prototype.removeListeners = function() {
|
||||
$(SELECTORS.CATEGORY_LINK).off('click');
|
||||
};
|
||||
|
||||
return /** @alias module:tool_dataprivacy/add_category */ {
|
||||
getInstance: function(contextId) {
|
||||
return new AddCategory(contextId);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Module to add purposes.
|
||||
*
|
||||
* @module tool_dataprivacy/add_purpose
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/str', 'core/ajax', 'core/notification', 'core/modal_factory', 'core/modal_events', 'core/fragment'],
|
||||
function($, Str, Ajax, Notification, ModalFactory, ModalEvents, Fragment) {
|
||||
|
||||
var SELECTORS = {
|
||||
PURPOSE_LINK: '[data-add-element="purpose"]',
|
||||
};
|
||||
|
||||
var AddPurpose = function(contextId) {
|
||||
this.contextId = contextId;
|
||||
|
||||
var stringKeys = [
|
||||
{
|
||||
key: 'addpurpose',
|
||||
component: 'tool_dataprivacy'
|
||||
},
|
||||
{
|
||||
key: 'save',
|
||||
component: 'admin'
|
||||
}
|
||||
];
|
||||
this.strings = Str.get_strings(stringKeys);
|
||||
|
||||
this.registerEventListeners();
|
||||
};
|
||||
|
||||
/**
|
||||
* @var {int} contextId
|
||||
* @private
|
||||
*/
|
||||
AddPurpose.prototype.contextId = 0;
|
||||
|
||||
/**
|
||||
* @var {Promise}
|
||||
* @private
|
||||
*/
|
||||
AddPurpose.prototype.strings = 0;
|
||||
|
||||
AddPurpose.prototype.registerEventListeners = function() {
|
||||
|
||||
var trigger = $(SELECTORS.PURPOSE_LINK);
|
||||
trigger.on('click', function() {
|
||||
return this.strings.then(function(strings) {
|
||||
ModalFactory.create({
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
title: strings[0],
|
||||
body: '',
|
||||
}, trigger).done(function(modal) {
|
||||
this.setupFormModal(modal, strings[1]);
|
||||
}.bind(this));
|
||||
}.bind(this))
|
||||
.fail(Notification.exception);
|
||||
}.bind(this));
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @method getBody
|
||||
* @param {Object} formdata
|
||||
* @private
|
||||
* @return {Promise}
|
||||
*/
|
||||
AddPurpose.prototype.getBody = function(formdata) {
|
||||
|
||||
var params = null;
|
||||
if (typeof formdata !== "undefined") {
|
||||
params = {jsonformdata: JSON.stringify(formdata)};
|
||||
}
|
||||
// Get the content of the modal.
|
||||
return Fragment.loadFragment('tool_dataprivacy', 'addpurpose_form', this.contextId, params);
|
||||
};
|
||||
|
||||
AddPurpose.prototype.setupFormModal = function(modal, saveText) {
|
||||
modal.setLarge();
|
||||
|
||||
modal.setSaveButtonText(saveText);
|
||||
|
||||
// We want to reset the form every time it is opened.
|
||||
modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));
|
||||
|
||||
modal.setBody(this.getBody());
|
||||
|
||||
// We catch the modal save event, and use it to submit the form inside the modal.
|
||||
// Triggering a form submission will give JS validation scripts a chance to check for errors.
|
||||
modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
|
||||
// We also catch the form submit event and use it to submit the form with ajax.
|
||||
modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
|
||||
|
||||
this.modal = modal;
|
||||
|
||||
modal.show();
|
||||
};
|
||||
|
||||
/**
|
||||
* This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
|
||||
*
|
||||
* @method submitForm
|
||||
* @param {Event} e Form submission event.
|
||||
* @private
|
||||
*/
|
||||
AddPurpose.prototype.submitForm = function(e) {
|
||||
e.preventDefault();
|
||||
this.modal.getRoot().find('form').submit();
|
||||
};
|
||||
|
||||
AddPurpose.prototype.submitFormAjax = function(e) {
|
||||
// We don't want to do a real form submission.
|
||||
e.preventDefault();
|
||||
|
||||
// Convert all the form elements values to a serialised string.
|
||||
var formData = this.modal.getRoot().find('form').serialize();
|
||||
|
||||
Ajax.call([{
|
||||
methodname: 'tool_dataprivacy_create_purpose_form',
|
||||
args: {jsonformdata: JSON.stringify(formData)},
|
||||
done: function(data) {
|
||||
if (data.validationerrors) {
|
||||
this.modal.setBody(this.getBody(formData));
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}.bind(this),
|
||||
|
||||
fail: Notification.exception
|
||||
}]);
|
||||
};
|
||||
|
||||
AddPurpose.prototype.close = function() {
|
||||
this.destroy();
|
||||
document.location.reload();
|
||||
};
|
||||
|
||||
AddPurpose.prototype.destroy = function() {
|
||||
Y.use('moodle-core-formchangechecker', function() {
|
||||
M.core_formchangechecker.reset_form_dirty_state();
|
||||
});
|
||||
this.modal.destroy();
|
||||
};
|
||||
|
||||
AddPurpose.prototype.removeListeners = function() {
|
||||
$(SELECTORS.PURPOSE_LINK).off('click');
|
||||
};
|
||||
|
||||
return /** @alias module:tool_dataprivacy/add_purpose */ {
|
||||
getInstance: function(contextId) {
|
||||
return new AddPurpose(contextId);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* AMD module for categories actions.
|
||||
*
|
||||
* @module tool_dataprivacy/categoriesactions
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/modal_factory',
|
||||
'core/modal_events'],
|
||||
function($, Ajax, Notification, Str, ModalFactory, ModalEvents) {
|
||||
|
||||
/**
|
||||
* List of action selectors.
|
||||
*
|
||||
* @type {{DELETE: string}}
|
||||
*/
|
||||
var ACTIONS = {
|
||||
DELETE: '[data-action="deletecategory"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* CategoriesActions class.
|
||||
*/
|
||||
var CategoriesActions = function() {
|
||||
this.registerEvents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Register event listeners.
|
||||
*/
|
||||
CategoriesActions.prototype.registerEvents = function() {
|
||||
$(ACTIONS.DELETE).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var id = $(this).data('id');
|
||||
var categoryname = $(this).data('name');
|
||||
var stringkeys = [
|
||||
{
|
||||
key: 'deletecategory',
|
||||
component: 'tool_dataprivacy',
|
||||
param: categoryname
|
||||
},
|
||||
{
|
||||
key: 'deletecategorytext',
|
||||
component: 'tool_dataprivacy',
|
||||
param: categoryname
|
||||
}
|
||||
];
|
||||
|
||||
Str.get_strings(stringkeys).then(function(langStrings) {
|
||||
var title = langStrings[0];
|
||||
var confirmMessage = langStrings[1];
|
||||
return ModalFactory.create({
|
||||
title: title,
|
||||
body: confirmMessage,
|
||||
type: ModalFactory.types.SAVE_CANCEL
|
||||
}).then(function(modal) {
|
||||
modal.setSaveButtonText(title);
|
||||
|
||||
// Handle save event.
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
|
||||
var request = {
|
||||
methodname: 'tool_dataprivacy_delete_category',
|
||||
args: {'id': id}
|
||||
};
|
||||
|
||||
Ajax.call([request])[0].done(function(data) {
|
||||
if (data.result) {
|
||||
$('tr[data-categoryid="' + id + '"]').remove();
|
||||
} else {
|
||||
Notification.addNotification({
|
||||
message: data.warnings[0].message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
});
|
||||
}).done(function(modal) {
|
||||
modal.show();
|
||||
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
};
|
||||
|
||||
return /** @alias module:tool_dataprivacy/categoriesactions */ {
|
||||
// Public variables and functions.
|
||||
|
||||
/**
|
||||
* Initialise the module.
|
||||
*
|
||||
* @method init
|
||||
* @return {CategoriesActions}
|
||||
*/
|
||||
'init': function() {
|
||||
return new CategoriesActions();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,156 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Request actions.
|
||||
*
|
||||
* @module tool_dataprivacy/data_deletion
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/modal_factory',
|
||||
'core/modal_events'],
|
||||
function($, Ajax, Notification, Str, ModalFactory, ModalEvents) {
|
||||
|
||||
/**
|
||||
* List of action selectors.
|
||||
*
|
||||
* @type {{MARK_FOR_DELETION: string}}
|
||||
* @type {{SELECT_ALL: string}}
|
||||
*/
|
||||
var ACTIONS = {
|
||||
MARK_FOR_DELETION: '[data-action="markfordeletion"]',
|
||||
SELECT_ALL: '[data-action="selectall"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* List of selectors.
|
||||
*
|
||||
* @type {{SELECTCONTEXT: string}}
|
||||
*/
|
||||
var SELECTORS = {
|
||||
SELECTCONTEXT: '.selectcontext',
|
||||
};
|
||||
|
||||
/**
|
||||
* DataDeletionActions class.
|
||||
*/
|
||||
var DataDeletionActions = function() {
|
||||
this.registerEvents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Register event listeners.
|
||||
*/
|
||||
DataDeletionActions.prototype.registerEvents = function() {
|
||||
$(ACTIONS.MARK_FOR_DELETION).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var selectedIds = [];
|
||||
$(SELECTORS.SELECTCONTEXT).each(function() {
|
||||
var checkbox = $(this);
|
||||
if (checkbox.is(':checked')) {
|
||||
selectedIds.push(checkbox.val());
|
||||
}
|
||||
});
|
||||
showConfirmation(selectedIds);
|
||||
});
|
||||
|
||||
$(ACTIONS.SELECT_ALL).change(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var selectallnone = $(this);
|
||||
if (selectallnone.is(':checked')) {
|
||||
$(SELECTORS.SELECTCONTEXT).attr('checked', 'checked');
|
||||
} else {
|
||||
$(SELECTORS.SELECTCONTEXT).removeAttr('checked');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the confirmation dialogue.
|
||||
*
|
||||
* @param {Array} ids The array of expired context record IDs.
|
||||
*/
|
||||
function showConfirmation(ids) {
|
||||
var keys = [
|
||||
{
|
||||
key: 'confirm',
|
||||
component: 'moodle'
|
||||
},
|
||||
{
|
||||
key: 'confirmcontextdeletion',
|
||||
component: 'tool_dataprivacy'
|
||||
}
|
||||
];
|
||||
var wsfunction = 'tool_dataprivacy_confirm_contexts_for_deletion';
|
||||
|
||||
var modalTitle = '';
|
||||
Str.get_strings(keys).then(function(langStrings) {
|
||||
modalTitle = langStrings[0];
|
||||
var confirmMessage = langStrings[1];
|
||||
return ModalFactory.create({
|
||||
title: modalTitle,
|
||||
body: confirmMessage,
|
||||
type: ModalFactory.types.SAVE_CANCEL
|
||||
});
|
||||
}).then(function(modal) {
|
||||
modal.setSaveButtonText(modalTitle);
|
||||
|
||||
// Handle save event.
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
// Confirm the request.
|
||||
var params = {
|
||||
'ids': ids
|
||||
};
|
||||
|
||||
var request = {
|
||||
methodname: wsfunction,
|
||||
args: params
|
||||
};
|
||||
|
||||
Ajax.call([request])[0].done(function(data) {
|
||||
if (data.result) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
Notification.addNotification({
|
||||
message: data.warnings[0].message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
}).done(function(modal) {
|
||||
modal.show();
|
||||
}).fail(Notification.exception);
|
||||
}
|
||||
|
||||
return DataDeletionActions;
|
||||
});
|
||||
@@ -1,317 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Request actions.
|
||||
*
|
||||
* @module tool_dataprivacy/data_registry
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/str', 'core/ajax', 'core/notification', 'core/templates', 'core/modal_factory',
|
||||
'core/modal_events', 'core/fragment', 'tool_dataprivacy/add_purpose', 'tool_dataprivacy/add_category'],
|
||||
function($, Str, Ajax, Notification, Templates, ModalFactory, ModalEvents, Fragment, AddPurpose, AddCategory) {
|
||||
|
||||
var SELECTORS = {
|
||||
TREE_NODES: '[data-context-tree-node=1]',
|
||||
FORM_CONTAINER: '#context-form-container',
|
||||
};
|
||||
|
||||
var DataRegistry = function(systemContextId, initContextLevel, initContextId) {
|
||||
this.systemContextId = systemContextId;
|
||||
this.currentContextLevel = initContextLevel;
|
||||
this.currentContextId = initContextId;
|
||||
this.init();
|
||||
};
|
||||
|
||||
/**
|
||||
* @var {int} systemContextId
|
||||
* @private
|
||||
*/
|
||||
DataRegistry.prototype.systemContextId = 0;
|
||||
|
||||
/**
|
||||
* @var {int} currentContextLevel
|
||||
* @private
|
||||
*/
|
||||
DataRegistry.prototype.currentContextLevel = 0;
|
||||
|
||||
/**
|
||||
* @var {int} currentContextId
|
||||
* @private
|
||||
*/
|
||||
DataRegistry.prototype.currentContextId = 0;
|
||||
|
||||
/**
|
||||
* @var {AddPurpose} addpurpose
|
||||
* @private
|
||||
*/
|
||||
DataRegistry.prototype.addpurpose = null;
|
||||
|
||||
/**
|
||||
* @var {AddCategory} addcategory
|
||||
* @private
|
||||
*/
|
||||
DataRegistry.prototype.addcategory = null;
|
||||
|
||||
DataRegistry.prototype.init = function() {
|
||||
// Add purpose and category modals always at system context.
|
||||
this.addpurpose = AddPurpose.getInstance(this.systemContextId);
|
||||
this.addcategory = AddCategory.getInstance(this.systemContextId);
|
||||
|
||||
var stringKeys = [
|
||||
{
|
||||
key: 'changessaved',
|
||||
component: 'moodle'
|
||||
}, {
|
||||
key: 'contextpurposecategorysaved',
|
||||
component: 'tool_dataprivacy'
|
||||
}, {
|
||||
key: 'noblockstoload',
|
||||
component: 'tool_dataprivacy'
|
||||
}, {
|
||||
key: 'noactivitiestoload',
|
||||
component: 'tool_dataprivacy'
|
||||
}, {
|
||||
key: 'nocoursestoload',
|
||||
component: 'tool_dataprivacy'
|
||||
}
|
||||
];
|
||||
this.strings = Str.get_strings(stringKeys);
|
||||
|
||||
this.registerEventListeners();
|
||||
|
||||
// Load the default context level form.
|
||||
if (this.currentContextId) {
|
||||
this.loadForm('context_form', [this.currentContextId], this.submitContextFormAjax.bind(this));
|
||||
} else {
|
||||
this.loadForm('contextlevel_form', [this.currentContextLevel], this.submitContextLevelFormAjax.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
DataRegistry.prototype.registerEventListeners = function() {
|
||||
$(SELECTORS.TREE_NODES).on('click', function(ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
var trigger = $(ev.currentTarget);
|
||||
|
||||
// Active node.
|
||||
$(SELECTORS.TREE_NODES).removeClass('active');
|
||||
trigger.addClass('active');
|
||||
|
||||
var contextLevel = trigger.data('contextlevel');
|
||||
var contextId = trigger.data('contextid');
|
||||
if (contextLevel) {
|
||||
// Context level level.
|
||||
|
||||
window.history.pushState({}, null, '?contextlevel=' + contextLevel);
|
||||
|
||||
// Remove previous add purpose and category listeners to avoid memory leaks.
|
||||
this.addpurpose.removeListeners();
|
||||
this.addcategory.removeListeners();
|
||||
|
||||
// Load the context level form.
|
||||
this.currentContextLevel = contextLevel;
|
||||
this.loadForm('contextlevel_form', [this.currentContextLevel], this.submitContextLevelFormAjax.bind(this));
|
||||
} else if (contextId) {
|
||||
// Context instance level.
|
||||
|
||||
window.history.pushState({}, null, '?contextid=' + contextId);
|
||||
|
||||
// Remove previous add purpose and category listeners to avoid memory leaks.
|
||||
this.addpurpose.removeListeners();
|
||||
this.addcategory.removeListeners();
|
||||
|
||||
// Load the context level form.
|
||||
this.currentContextId = contextId;
|
||||
this.loadForm('context_form', [this.currentContextId], this.submitContextFormAjax.bind(this));
|
||||
} else {
|
||||
// Expandable nodes.
|
||||
|
||||
var expandContextId = trigger.data('expandcontextid');
|
||||
var expandElement = trigger.data('expandelement');
|
||||
var expanded = trigger.data('expanded');
|
||||
|
||||
// Extra checking that there is an expandElement because we remove it after loading 0 branches.
|
||||
if (expandElement) {
|
||||
|
||||
if (!expanded) {
|
||||
if (trigger.data('loaded') || !expandContextId || !expandElement) {
|
||||
this.expand(trigger);
|
||||
} else {
|
||||
|
||||
trigger.find('> i').removeClass('fa-plus');
|
||||
trigger.find('> i').addClass('fa-circle-o-notch fa-spin');
|
||||
this.loadExtra(trigger, expandContextId, expandElement);
|
||||
}
|
||||
} else {
|
||||
this.collapse(trigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
DataRegistry.prototype.removeListeners = function() {
|
||||
$(SELECTORS.TREE_NODES).off('click');
|
||||
};
|
||||
|
||||
DataRegistry.prototype.loadForm = function(fragmentName, fragmentArgs, formSubmitCallback) {
|
||||
|
||||
this.clearForm();
|
||||
|
||||
var fragment = Fragment.loadFragment('tool_dataprivacy', fragmentName, this.systemContextId, fragmentArgs);
|
||||
fragment.done(function(html, js) {
|
||||
|
||||
$(SELECTORS.FORM_CONTAINER).html(html);
|
||||
Templates.runTemplateJS(js);
|
||||
|
||||
this.addpurpose.registerEventListeners();
|
||||
this.addcategory.registerEventListeners();
|
||||
|
||||
// We also catch the form submit event and use it to submit the form with ajax.
|
||||
$(SELECTORS.FORM_CONTAINER).on('submit', 'form', formSubmitCallback);
|
||||
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
DataRegistry.prototype.clearForm = function() {
|
||||
// For the previously loaded form.
|
||||
Y.use('moodle-core-formchangechecker', function() {
|
||||
M.core_formchangechecker.reset_form_dirty_state();
|
||||
});
|
||||
|
||||
// Remove previous listeners.
|
||||
$(SELECTORS.FORM_CONTAINER).off('submit', 'form');
|
||||
};
|
||||
|
||||
/**
|
||||
* This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
|
||||
*
|
||||
* @method submitForm
|
||||
* @param {Event} e Form submission event.
|
||||
* @private
|
||||
*/
|
||||
DataRegistry.prototype.submitForm = function(e) {
|
||||
e.preventDefault();
|
||||
$(SELECTORS.FORM_CONTAINER).find('form').submit();
|
||||
};
|
||||
|
||||
DataRegistry.prototype.submitContextLevelFormAjax = function(e) {
|
||||
this.submitFormAjax(e, 'tool_dataprivacy_set_contextlevel_form');
|
||||
};
|
||||
|
||||
DataRegistry.prototype.submitContextFormAjax = function(e) {
|
||||
this.submitFormAjax(e, 'tool_dataprivacy_set_context_form');
|
||||
};
|
||||
|
||||
DataRegistry.prototype.submitFormAjax = function(e, saveMethodName) {
|
||||
// We don't want to do a real form submission.
|
||||
e.preventDefault();
|
||||
|
||||
// Convert all the form elements values to a serialised string.
|
||||
var formData = $(SELECTORS.FORM_CONTAINER).find('form').serialize();
|
||||
return this.strings.then(function(strings) {
|
||||
Ajax.call([{
|
||||
methodname: saveMethodName,
|
||||
args: {jsonformdata: JSON.stringify(formData)},
|
||||
done: function() {
|
||||
Notification.alert(strings[0], strings[1]);
|
||||
},
|
||||
fail: Notification.exception
|
||||
}]);
|
||||
}).catch(Notification.exception);
|
||||
|
||||
};
|
||||
|
||||
DataRegistry.prototype.loadExtra = function(parentNode, expandContextId, expandElement) {
|
||||
|
||||
Ajax.call([{
|
||||
methodname: 'tool_dataprivacy_tree_extra_branches',
|
||||
args: {
|
||||
contextid: expandContextId,
|
||||
element: expandElement,
|
||||
},
|
||||
done: function(data) {
|
||||
if (data.branches.length == 0) {
|
||||
this.noElements(parentNode, expandElement);
|
||||
return;
|
||||
}
|
||||
Templates.render('tool_dataprivacy/context_tree_branches', data)
|
||||
.then(function(html) {
|
||||
parentNode.after(html);
|
||||
this.removeListeners();
|
||||
this.registerEventListeners();
|
||||
this.expand(parentNode);
|
||||
parentNode.data('loaded', 1);
|
||||
return;
|
||||
}.bind(this))
|
||||
.fail(Notification.exception);
|
||||
}.bind(this),
|
||||
fail: Notification.exception
|
||||
}]);
|
||||
};
|
||||
|
||||
DataRegistry.prototype.noElements = function(node, expandElement) {
|
||||
node.data('expandcontextid', '');
|
||||
node.data('expandelement', '');
|
||||
this.strings.then(function(strings) {
|
||||
|
||||
// 2 = blocks, 3 = activities, 4 = courses (although courses is not likely really).
|
||||
var key = 2;
|
||||
if (expandElement == 'module') {
|
||||
key = 3;
|
||||
} else if (expandElement == 'course') {
|
||||
key = 4;
|
||||
}
|
||||
node.text(strings[key]);
|
||||
return;
|
||||
}).fail(Notification.exception);
|
||||
};
|
||||
|
||||
DataRegistry.prototype.collapse = function(node) {
|
||||
node.data('expanded', 0);
|
||||
node.siblings('nav').addClass('hidden');
|
||||
node.find('> i').removeClass('fa-minus');
|
||||
node.find('> i').addClass('fa-plus');
|
||||
};
|
||||
|
||||
DataRegistry.prototype.expand = function(node) {
|
||||
node.data('expanded', 1);
|
||||
node.siblings('nav').removeClass('hidden');
|
||||
node.find('> i').removeClass('fa-plus');
|
||||
// Also remove the spinning one if data was just loaded.
|
||||
node.find('> i').removeClass('fa-circle-o-notch fa-spin');
|
||||
node.find('> i').addClass('fa-minus');
|
||||
};
|
||||
return /** @alias module:tool_dataprivacy/data_registry */ {
|
||||
|
||||
/**
|
||||
* Initialise the page.
|
||||
*
|
||||
* @param {Number} systemContextId
|
||||
* @param {Number} initContextLevel
|
||||
* @param {Number} initContextId
|
||||
* @return {DataRegistry}
|
||||
*/
|
||||
init: function(systemContextId, initContextLevel, initContextId) {
|
||||
return new DataRegistry(systemContextId, initContextLevel, initContextId);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Request actions.
|
||||
*
|
||||
* @module tool_dataprivacy/data_request_modal
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_registry',
|
||||
'tool_dataprivacy/events'],
|
||||
function($, Notification, CustomEvents, Modal, ModalRegistry, DataPrivacyEvents) {
|
||||
|
||||
var registered = false;
|
||||
var SELECTORS = {
|
||||
APPROVE_BUTTON: '[data-action="approve"]',
|
||||
DENY_BUTTON: '[data-action="deny"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for the Modal.
|
||||
*
|
||||
* @param {object} root The root jQuery element for the modal
|
||||
*/
|
||||
var ModalDataRequest = function(root) {
|
||||
Modal.call(this, root);
|
||||
|
||||
if (!this.getFooter().find(SELECTORS.APPROVE_BUTTON).length) {
|
||||
Notification.exception({message: 'No approve button found'});
|
||||
}
|
||||
|
||||
if (!this.getFooter().find(SELECTORS.DENY_BUTTON).length) {
|
||||
Notification.exception({message: 'No deny button found'});
|
||||
}
|
||||
};
|
||||
|
||||
ModalDataRequest.TYPE = 'tool_dataprivacy-data_request';
|
||||
ModalDataRequest.prototype = Object.create(Modal.prototype);
|
||||
ModalDataRequest.prototype.constructor = ModalDataRequest;
|
||||
|
||||
/**
|
||||
* Set up all of the event handling for the modal.
|
||||
*
|
||||
* @method registerEventListeners
|
||||
*/
|
||||
ModalDataRequest.prototype.registerEventListeners = function() {
|
||||
// Apply parent event listeners.
|
||||
Modal.prototype.registerEventListeners.call(this);
|
||||
|
||||
this.getModal().on(CustomEvents.events.activate, SELECTORS.APPROVE_BUTTON, function(e, data) {
|
||||
var approveEvent = $.Event(DataPrivacyEvents.approve);
|
||||
this.getRoot().trigger(approveEvent, this);
|
||||
|
||||
if (!approveEvent.isDefaultPrevented()) {
|
||||
this.hide();
|
||||
data.originalEvent.preventDefault();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this.getModal().on(CustomEvents.events.activate, SELECTORS.DENY_BUTTON, function(e, data) {
|
||||
var denyEvent = $.Event(DataPrivacyEvents.deny);
|
||||
this.getRoot().trigger(denyEvent, this);
|
||||
|
||||
if (!denyEvent.isDefaultPrevented()) {
|
||||
this.hide();
|
||||
data.originalEvent.preventDefault();
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
// Automatically register with the modal registry the first time this module is imported so that you can create modals
|
||||
// of this type using the modal factory.
|
||||
if (!registered) {
|
||||
ModalRegistry.register(ModalDataRequest.TYPE, ModalDataRequest, 'tool_dataprivacy/data_request_modal');
|
||||
registered = true;
|
||||
}
|
||||
|
||||
return ModalDataRequest;
|
||||
});
|
||||
@@ -1,92 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Module to update the displayed retention period.
|
||||
*
|
||||
* @module tool_dataprivacy/effective_retention_period
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery'],
|
||||
function($) {
|
||||
|
||||
var SELECTORS = {
|
||||
PURPOSE_SELECT: '#id_purposeid',
|
||||
RETENTION_FIELD_BOOST: '#id_error_retention_current',
|
||||
RETENTION_FIELD_CLEAN: '#fitem_id_retention_current [data-fieldtype=static]',
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for the retention period display.
|
||||
*
|
||||
* @param {Array} purposeRetentionPeriods Associative array of purposeids with effective retention period at this context
|
||||
*/
|
||||
var EffectiveRetentionPeriod = function(purposeRetentionPeriods) {
|
||||
this.purposeRetentionPeriods = purposeRetentionPeriods;
|
||||
this.registerEventListeners();
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the current 'change' listeners.
|
||||
*
|
||||
* Useful when a new form is loaded.
|
||||
*/
|
||||
var removeListeners = function() {
|
||||
$(SELECTORS.PURPOSE_SELECT).off('change');
|
||||
};
|
||||
|
||||
/**
|
||||
* @var {Array} purposeRetentionPeriods
|
||||
* @private
|
||||
*/
|
||||
EffectiveRetentionPeriod.prototype.purposeRetentionPeriods = [];
|
||||
|
||||
/**
|
||||
* Add purpose change listeners.
|
||||
*
|
||||
* @method registerEventListeners
|
||||
*/
|
||||
EffectiveRetentionPeriod.prototype.registerEventListeners = function() {
|
||||
|
||||
$(SELECTORS.PURPOSE_SELECT).on('change', function(ev) {
|
||||
var selected = $(ev.currentTarget).val();
|
||||
var selectedPurpose = this.purposeRetentionPeriods[selected];
|
||||
|
||||
var cleanSelector = $(SELECTORS.RETENTION_FIELD_CLEAN);
|
||||
if (cleanSelector.length > 0) {
|
||||
cleanSelector.text(selectedPurpose);
|
||||
} else {
|
||||
var boostSelector = $(SELECTORS.RETENTION_FIELD_BOOST);
|
||||
var retentionField = boostSelector.siblings();
|
||||
if (retentionField.length > 0) {
|
||||
retentionField.text(selectedPurpose);
|
||||
}
|
||||
}
|
||||
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
return /** @alias module:tool_dataprivacy/effective_retention_period */ {
|
||||
init: function(purposeRetentionPeriods) {
|
||||
// Remove previously attached listeners.
|
||||
removeListeners();
|
||||
return new EffectiveRetentionPeriod(purposeRetentionPeriods);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Contain the events the data privacy tool can fire.
|
||||
*
|
||||
* @module tool_dataprivacy/events
|
||||
* @class events
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([], function() {
|
||||
return {
|
||||
approve: 'tool_dataprivacy-data_request:approve',
|
||||
deny: 'tool_dataprivacy-data_request:deny',
|
||||
};
|
||||
});
|
||||
@@ -1,89 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Potential user selector module.
|
||||
*
|
||||
* @module tool_dataprivacy/expand_contract
|
||||
* @class page-expand-contract
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Adrian Greeve
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define(['jquery', 'core/url', 'core/str'], function($, url, str) {
|
||||
|
||||
var expandedImage = $('<img alt="" src="' + url.imageUrl('t/expanded') + '"/>');
|
||||
var collapsedImage = $('<img alt="" src="' + url.imageUrl('t/collapsed') + '"/>');
|
||||
|
||||
return /** @alias module:tool_dataprivacy/expand-collapse */ {
|
||||
/**
|
||||
* Expand or collapse a selected node.
|
||||
*
|
||||
* @param {object} targetnode The node that we want to expand / collapse
|
||||
* @param {object} thisnode The node that was clicked.
|
||||
* @return {null}
|
||||
*/
|
||||
expandCollapse: function(targetnode, thisnode) {
|
||||
if (targetnode.hasClass('hide')) {
|
||||
targetnode.removeClass('hide');
|
||||
targetnode.addClass('visible');
|
||||
targetnode.attr('aria-expanded', true);
|
||||
thisnode.find(':header i.fa').removeClass('fa-plus-square');
|
||||
thisnode.find(':header i.fa').addClass('fa-minus-square');
|
||||
thisnode.find(':header img.icon').attr('src', expandedImage.attr('src'));
|
||||
} else {
|
||||
targetnode.removeClass('visible');
|
||||
targetnode.addClass('hide');
|
||||
targetnode.attr('aria-expanded', false);
|
||||
thisnode.find(':header i.fa').removeClass('fa-minus-square');
|
||||
thisnode.find(':header i.fa').addClass('fa-plus-square');
|
||||
thisnode.find(':header img.icon').attr('src', collapsedImage.attr('src'));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Expand or collapse all nodes on this page.
|
||||
*
|
||||
* @param {string} nextstate The next state to change to.
|
||||
* @return {null}
|
||||
*/
|
||||
expandCollapseAll: function(nextstate) {
|
||||
var currentstate = (nextstate == 'visible') ? 'hide' : 'visible';
|
||||
var ariaexpandedstate = (nextstate == 'visible') ? true : false;
|
||||
var iconclassnow = (nextstate == 'visible') ? 'fa-plus-square' : 'fa-minus-square';
|
||||
var iconclassnext = (nextstate == 'visible') ? 'fa-minus-square' : 'fa-plus-square';
|
||||
var imagenow = (nextstate == 'visible') ? expandedImage.attr('src') : collapsedImage.attr('src');
|
||||
$('.' + currentstate).each(function() {
|
||||
$(this).removeClass(currentstate);
|
||||
$(this).addClass(nextstate);
|
||||
$(this).attr('aria-expanded', ariaexpandedstate);
|
||||
});
|
||||
$('.tool_dataprivacy-expand-all').data('visibilityState', currentstate);
|
||||
|
||||
str.get_string(currentstate, 'tool_dataprivacy').then(function(langString) {
|
||||
$('.tool_dataprivacy-expand-all').html(langString);
|
||||
}).catch(Notification.exception);
|
||||
|
||||
$(':header i.fa').each(function() {
|
||||
$(this).removeClass(iconclassnow);
|
||||
$(this).addClass(iconclassnext);
|
||||
});
|
||||
$(':header img.icon').each(function() {
|
||||
$(this).attr('src', imagenow);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,76 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Potential user selector module.
|
||||
*
|
||||
* @module tool_dataprivacy/form-user-selector
|
||||
* @class form-user-selector
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define(['jquery', 'core/ajax', 'core/templates'], function($, Ajax, Templates) {
|
||||
|
||||
return /** @alias module:tool_dataprivacy/form-user-selector */ {
|
||||
|
||||
processResults: function(selector, results) {
|
||||
var users = [];
|
||||
$.each(results, function(index, user) {
|
||||
users.push({
|
||||
value: user.id,
|
||||
label: user._label
|
||||
});
|
||||
});
|
||||
return users;
|
||||
},
|
||||
|
||||
transport: function(selector, query, success, failure) {
|
||||
var promise;
|
||||
|
||||
promise = Ajax.call([{
|
||||
methodname: 'tool_dataprivacy_get_users',
|
||||
args: {
|
||||
query: query
|
||||
}
|
||||
}]);
|
||||
|
||||
promise[0].then(function(results) {
|
||||
var promises = [],
|
||||
i = 0;
|
||||
|
||||
// Render the label.
|
||||
$.each(results, function(index, user) {
|
||||
promises.push(Templates.render('tool_dataprivacy/form-user-selector-suggestion', user));
|
||||
});
|
||||
|
||||
// Apply the label to the results.
|
||||
return $.when.apply($.when, promises).then(function() {
|
||||
var args = arguments;
|
||||
$.each(results, function(index, user) {
|
||||
user._label = args[i];
|
||||
i++;
|
||||
});
|
||||
success(results);
|
||||
return;
|
||||
});
|
||||
|
||||
}).fail(failure);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,221 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* AMD module to enable users to manage their own data requests.
|
||||
*
|
||||
* @module tool_dataprivacy/myrequestactions
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/modal_factory',
|
||||
'core/modal_events',
|
||||
'core/templates'],
|
||||
function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates) {
|
||||
|
||||
/**
|
||||
* List of action selectors.
|
||||
*
|
||||
* @type {{CANCEL_REQUEST: string}}
|
||||
* @type {{CONTACT_DPO: string}}
|
||||
*/
|
||||
var ACTIONS = {
|
||||
CANCEL_REQUEST: '[data-action="cancel"]',
|
||||
CONTACT_DPO: '[data-action="contactdpo"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* MyRequestActions class.
|
||||
*/
|
||||
var MyRequestActions = function() {
|
||||
this.registerEvents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Register event listeners.
|
||||
*/
|
||||
MyRequestActions.prototype.registerEvents = function() {
|
||||
$(ACTIONS.CANCEL_REQUEST).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var requestId = $(this).data('requestid');
|
||||
var stringkeys = [
|
||||
{
|
||||
key: 'cancelrequest',
|
||||
component: 'tool_dataprivacy'
|
||||
},
|
||||
{
|
||||
key: 'cancelrequestconfirmation',
|
||||
component: 'tool_dataprivacy'
|
||||
}
|
||||
];
|
||||
|
||||
Str.get_strings(stringkeys).then(function(langStrings) {
|
||||
var title = langStrings[0];
|
||||
var confirmMessage = langStrings[1];
|
||||
return ModalFactory.create({
|
||||
title: title,
|
||||
body: confirmMessage,
|
||||
type: ModalFactory.types.SAVE_CANCEL
|
||||
}).then(function(modal) {
|
||||
modal.setSaveButtonText(title);
|
||||
|
||||
// Handle save event.
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
// Cancel the request.
|
||||
var params = {
|
||||
'requestid': requestId
|
||||
};
|
||||
|
||||
var request = {
|
||||
methodname: 'tool_dataprivacy_cancel_data_request',
|
||||
args: params
|
||||
};
|
||||
|
||||
Ajax.call([request])[0].done(function(data) {
|
||||
if (data.result) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
Notification.addNotification({
|
||||
message: data.warnings[0].message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
});
|
||||
}).done(function(modal) {
|
||||
// Show the modal!
|
||||
modal.show();
|
||||
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
$(ACTIONS.CONTACT_DPO).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var replyToEmail = $(this).data('replytoemail');
|
||||
|
||||
var keys = [
|
||||
{
|
||||
key: 'contactdataprotectionofficer',
|
||||
component: 'tool_dataprivacy'
|
||||
},
|
||||
{
|
||||
key: 'send',
|
||||
component: 'tool_dataprivacy'
|
||||
},
|
||||
];
|
||||
|
||||
var sendButtonText = '';
|
||||
Str.get_strings(keys).then(function(langStrings) {
|
||||
var modalTitle = langStrings[0];
|
||||
sendButtonText = langStrings[1];
|
||||
var context = {
|
||||
'replytoemail': replyToEmail
|
||||
};
|
||||
return ModalFactory.create({
|
||||
title: modalTitle,
|
||||
body: Templates.render('tool_dataprivacy/contact_dpo', context),
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
large: true
|
||||
});
|
||||
}).done(function(modal) {
|
||||
modal.setSaveButtonText(sendButtonText);
|
||||
|
||||
// Handle send event.
|
||||
modal.getRoot().on(ModalEvents.save, function(e) {
|
||||
var message = $('#message').val().trim();
|
||||
if (message.length === 0) {
|
||||
e.preventDefault();
|
||||
// Show validation error when the message is empty.
|
||||
$('[data-region="messageinput"]').addClass('has-danger notifyproblem');
|
||||
$('#id_error_message').removeAttr('hidden');
|
||||
} else {
|
||||
// Send the message.
|
||||
sendMessageToDPO(message);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
// Show the modal!
|
||||
modal.show();
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Send message to the Data Protection Officer.
|
||||
*
|
||||
* @param {String} message The message to send.
|
||||
*/
|
||||
function sendMessageToDPO(message) {
|
||||
var request = {
|
||||
methodname: 'tool_dataprivacy_contact_dpo',
|
||||
args: {
|
||||
message: message
|
||||
}
|
||||
};
|
||||
|
||||
var requestType = 'success';
|
||||
Ajax.call([request])[0].then(function(data) {
|
||||
if (data.result) {
|
||||
return Str.get_string('requestsubmitted', 'tool_dataprivacy');
|
||||
}
|
||||
requestType = 'error';
|
||||
return data.warnings.join('<br>');
|
||||
|
||||
}).done(function(message) {
|
||||
Notification.addNotification({
|
||||
message: message,
|
||||
type: requestType
|
||||
});
|
||||
|
||||
}).fail(Notification.exception);
|
||||
}
|
||||
|
||||
return /** @alias module:tool_dataprivacy/myrequestactions */ {
|
||||
// Public variables and functions.
|
||||
|
||||
/**
|
||||
* Initialise the unified user filter.
|
||||
*
|
||||
* @method init
|
||||
* @return {MyRequestActions}
|
||||
*/
|
||||
'init': function() {
|
||||
return new MyRequestActions();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,129 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* AMD module for purposes actions.
|
||||
*
|
||||
* @module tool_dataprivacy/purposesactions
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/modal_factory',
|
||||
'core/modal_events'],
|
||||
function($, Ajax, Notification, Str, ModalFactory, ModalEvents) {
|
||||
|
||||
/**
|
||||
* List of action selectors.
|
||||
*
|
||||
* @type {{DELETE: string}}
|
||||
*/
|
||||
var ACTIONS = {
|
||||
DELETE: '[data-action="deletepurpose"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* PurposesActions class.
|
||||
*/
|
||||
var PurposesActions = function() {
|
||||
this.registerEvents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Register event listeners.
|
||||
*/
|
||||
PurposesActions.prototype.registerEvents = function() {
|
||||
$(ACTIONS.DELETE).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var id = $(this).data('id');
|
||||
var purposename = $(this).data('name');
|
||||
var stringkeys = [
|
||||
{
|
||||
key: 'deletepurpose',
|
||||
component: 'tool_dataprivacy',
|
||||
param: purposename
|
||||
},
|
||||
{
|
||||
key: 'deletepurposetext',
|
||||
component: 'tool_dataprivacy',
|
||||
param: purposename
|
||||
}
|
||||
];
|
||||
|
||||
Str.get_strings(stringkeys).then(function(langStrings) {
|
||||
var title = langStrings[0];
|
||||
var confirmMessage = langStrings[1];
|
||||
return ModalFactory.create({
|
||||
title: title,
|
||||
body: confirmMessage,
|
||||
type: ModalFactory.types.SAVE_CANCEL
|
||||
}).then(function(modal) {
|
||||
modal.setSaveButtonText(title);
|
||||
|
||||
// Handle save event.
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
|
||||
var request = {
|
||||
methodname: 'tool_dataprivacy_delete_purpose',
|
||||
args: {'id': id}
|
||||
};
|
||||
|
||||
Ajax.call([request])[0].done(function(data) {
|
||||
if (data.result) {
|
||||
$('tr[data-purposeid="' + id + '"]').remove();
|
||||
} else {
|
||||
Notification.addNotification({
|
||||
message: data.warnings[0].message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
});
|
||||
}).done(function(modal) {
|
||||
modal.show();
|
||||
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
};
|
||||
|
||||
return /** @alias module:tool_dataprivacy/purposesactions */ {
|
||||
// Public variables and functions.
|
||||
|
||||
/**
|
||||
* Initialise the module.
|
||||
*
|
||||
* @method init
|
||||
* @return {PurposesActions}
|
||||
*/
|
||||
'init': function() {
|
||||
return new PurposesActions();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,227 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Request actions.
|
||||
*
|
||||
* @module tool_dataprivacy/requestactions
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/ajax',
|
||||
'core/notification',
|
||||
'core/str',
|
||||
'core/modal_factory',
|
||||
'core/modal_events',
|
||||
'core/templates',
|
||||
'tool_dataprivacy/data_request_modal',
|
||||
'tool_dataprivacy/events'],
|
||||
function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates, ModalDataRequest, DataPrivacyEvents) {
|
||||
|
||||
/**
|
||||
* List of action selectors.
|
||||
*
|
||||
* @type {{APPROVE_REQUEST: string}}
|
||||
* @type {{DENY_REQUEST: string}}
|
||||
* @type {{VIEW_REQUEST: string}}
|
||||
*/
|
||||
var ACTIONS = {
|
||||
APPROVE_REQUEST: '[data-action="approve"]',
|
||||
DENY_REQUEST: '[data-action="deny"]',
|
||||
VIEW_REQUEST: '[data-action="view"]'
|
||||
};
|
||||
|
||||
/**
|
||||
* RequestActions class.
|
||||
*/
|
||||
var RequestActions = function() {
|
||||
this.registerEvents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Register event listeners.
|
||||
*/
|
||||
RequestActions.prototype.registerEvents = function() {
|
||||
$(ACTIONS.VIEW_REQUEST).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var requestId = $(this).data('requestid');
|
||||
|
||||
// Cancel the request.
|
||||
var params = {
|
||||
'requestid': requestId
|
||||
};
|
||||
|
||||
var request = {
|
||||
methodname: 'tool_dataprivacy_get_data_request',
|
||||
args: params
|
||||
};
|
||||
|
||||
var promises = Ajax.call([request]);
|
||||
var modalTitle = '';
|
||||
var modalType = ModalFactory.types.DEFAULT;
|
||||
$.when(promises[0]).then(function(data) {
|
||||
if (data.result) {
|
||||
// Check if the status is awaiting approval.
|
||||
if (data.result.status == 2) {
|
||||
modalType = ModalDataRequest.TYPE;
|
||||
}
|
||||
modalTitle = data.result.typename;
|
||||
return Templates.render('tool_dataprivacy/request_details', data.result);
|
||||
}
|
||||
// Fail.
|
||||
Notification.addNotification({
|
||||
message: data.warnings[0].message,
|
||||
type: 'error'
|
||||
});
|
||||
return false;
|
||||
|
||||
}).then(function(html) {
|
||||
return ModalFactory.create({
|
||||
title: modalTitle,
|
||||
body: html,
|
||||
type: modalType,
|
||||
large: true
|
||||
}).then(function(modal) {
|
||||
// Handle approve event.
|
||||
modal.getRoot().on(DataPrivacyEvents.approve, function() {
|
||||
showConfirmation(DataPrivacyEvents.approve, requestId);
|
||||
});
|
||||
|
||||
// Handle deny event.
|
||||
modal.getRoot().on(DataPrivacyEvents.deny, function() {
|
||||
showConfirmation(DataPrivacyEvents.deny, requestId);
|
||||
});
|
||||
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
});
|
||||
}).done(function(modal) {
|
||||
// Show the modal!
|
||||
modal.show();
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
$(ACTIONS.APPROVE_REQUEST).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var requestId = $(this).data('requestid');
|
||||
showConfirmation(DataPrivacyEvents.approve, requestId);
|
||||
});
|
||||
|
||||
$(ACTIONS.DENY_REQUEST).click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var requestId = $(this).data('requestid');
|
||||
showConfirmation(DataPrivacyEvents.deny, requestId);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the confirmation dialogue.
|
||||
*
|
||||
* @param {String} action The action name.
|
||||
* @param {Number} requestId The request ID.
|
||||
*/
|
||||
function showConfirmation(action, requestId) {
|
||||
var keys = [];
|
||||
var wsfunction = '';
|
||||
switch (action) {
|
||||
case DataPrivacyEvents.approve:
|
||||
keys = [
|
||||
{
|
||||
key: 'approverequest',
|
||||
component: 'tool_dataprivacy'
|
||||
},
|
||||
{
|
||||
key: 'confirmapproval',
|
||||
component: 'tool_dataprivacy'
|
||||
}
|
||||
];
|
||||
wsfunction = 'tool_dataprivacy_approve_data_request';
|
||||
break;
|
||||
case DataPrivacyEvents.deny:
|
||||
keys = [
|
||||
{
|
||||
key: 'denyrequest',
|
||||
component: 'tool_dataprivacy'
|
||||
},
|
||||
{
|
||||
key: 'confirmdenial',
|
||||
component: 'tool_dataprivacy'
|
||||
}
|
||||
];
|
||||
wsfunction = 'tool_dataprivacy_deny_data_request';
|
||||
break;
|
||||
}
|
||||
|
||||
var modalTitle = '';
|
||||
Str.get_strings(keys).then(function(langStrings) {
|
||||
modalTitle = langStrings[0];
|
||||
var confirmMessage = langStrings[1];
|
||||
return ModalFactory.create({
|
||||
title: modalTitle,
|
||||
body: confirmMessage,
|
||||
type: ModalFactory.types.SAVE_CANCEL
|
||||
});
|
||||
}).then(function(modal) {
|
||||
modal.setSaveButtonText(modalTitle);
|
||||
|
||||
// Handle save event.
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
// Confirm the request.
|
||||
var params = {
|
||||
'requestid': requestId
|
||||
};
|
||||
|
||||
var request = {
|
||||
methodname: wsfunction,
|
||||
args: params
|
||||
};
|
||||
|
||||
Ajax.call([request])[0].done(function(data) {
|
||||
if (data.result) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
Notification.addNotification({
|
||||
message: data.warnings[0].message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
|
||||
// Handle hidden event.
|
||||
modal.getRoot().on(ModalEvents.hidden, function() {
|
||||
// Destroy when hidden.
|
||||
modal.destroy();
|
||||
});
|
||||
|
||||
return modal;
|
||||
}).done(function(modal) {
|
||||
modal.show();
|
||||
}).fail(Notification.exception);
|
||||
}
|
||||
|
||||
return RequestActions;
|
||||
});
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This page lets users manage categories.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
|
||||
$url = new moodle_url("/admin/tool/dataprivacy/categories.php");
|
||||
$title = get_string('editcategories', 'tool_dataprivacy');
|
||||
|
||||
\tool_dataprivacy\page_helper::setup($url, $title, 'dataregistry');
|
||||
|
||||
$output = $PAGE->get_renderer('tool_dataprivacy');
|
||||
echo $output->header();
|
||||
|
||||
$categories = \tool_dataprivacy\api::get_categories();
|
||||
$renderable = new \tool_dataprivacy\output\categories($categories);
|
||||
|
||||
echo $output->render($renderable);
|
||||
echo $output->footer();
|
||||
@@ -1,942 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Class containing helper methods for processing data requests.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_dataprivacy;
|
||||
|
||||
use coding_exception;
|
||||
use context_system;
|
||||
use core\invalid_persistent_exception;
|
||||
use core\message\message;
|
||||
use core\task\manager;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\contextlist_collection;
|
||||
use core_user;
|
||||
use dml_exception;
|
||||
use moodle_exception;
|
||||
use moodle_url;
|
||||
use required_capability_exception;
|
||||
use stdClass;
|
||||
use tool_dataprivacy\external\data_request_exporter;
|
||||
use tool_dataprivacy\local\helper;
|
||||
use tool_dataprivacy\task\initiate_data_request_task;
|
||||
use tool_dataprivacy\task\process_data_request_task;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class containing helper methods for processing data requests.
|
||||
*
|
||||
* @copyright 2018 Jun Pataleta
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class api {
|
||||
|
||||
/** Data export request type. */
|
||||
const DATAREQUEST_TYPE_EXPORT = 1;
|
||||
|
||||
/** Data deletion request type. */
|
||||
const DATAREQUEST_TYPE_DELETE = 2;
|
||||
|
||||
/** Other request type. Usually of enquiries to the DPO. */
|
||||
const DATAREQUEST_TYPE_OTHERS = 3;
|
||||
|
||||
/** Newly submitted and we haven't yet started finding out where they have data. */
|
||||
const DATAREQUEST_STATUS_PENDING = 0;
|
||||
|
||||
/** Newly submitted and we have started to find the location of data. */
|
||||
const DATAREQUEST_STATUS_PREPROCESSING = 1;
|
||||
|
||||
/** Metadata ready and awaiting review and approval by the Data Protection officer. */
|
||||
const DATAREQUEST_STATUS_AWAITING_APPROVAL = 2;
|
||||
|
||||
/** Request approved and will be processed soon. */
|
||||
const DATAREQUEST_STATUS_APPROVED = 3;
|
||||
|
||||
/** The request is now being processed. */
|
||||
const DATAREQUEST_STATUS_PROCESSING = 4;
|
||||
|
||||
/** Data request completed. */
|
||||
const DATAREQUEST_STATUS_COMPLETE = 5;
|
||||
|
||||
/** Data request cancelled by the user. */
|
||||
const DATAREQUEST_STATUS_CANCELLED = 6;
|
||||
|
||||
/** Data request rejected by the DPO. */
|
||||
const DATAREQUEST_STATUS_REJECTED = 7;
|
||||
|
||||
/**
|
||||
* Determines whether the user can contact the site's Data Protection Officer via Moodle.
|
||||
*
|
||||
* @return boolean True when tool_dataprivacy|contactdataprotectionofficer is enabled.
|
||||
* @throws dml_exception
|
||||
*/
|
||||
public static function can_contact_dpo() {
|
||||
return get_config('tool_dataprivacy', 'contactdataprotectionofficer') == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check's whether the current user has the capability to manage data requests.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
* @return bool
|
||||
* @throws coding_exception
|
||||
* @throws dml_exception
|
||||
*/
|
||||
public static function can_manage_data_requests($userid) {
|
||||
$context = context_system::instance();
|
||||
|
||||
// A user can manage data requests if he/she has the site DPO role and has the capability to manage data requests.
|
||||
return self::is_site_dpo($userid) && has_capability('tool/dataprivacy:managedatarequests', $context, $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user can manage the data registry at the provided id.
|
||||
*
|
||||
* @param int $contextid Fallback to system context id.
|
||||
* @throws \required_capability_exception
|
||||
* @return null
|
||||
*/
|
||||
public static function check_can_manage_data_registry($contextid = false) {
|
||||
if ($contextid) {
|
||||
$context = \context_helper::instance_by_id($contextid);
|
||||
} else {
|
||||
$context = \context_system::instance();
|
||||
}
|
||||
|
||||
require_capability('tool/dataprivacy:managedataregistry', $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the list of users with the Data Protection Officer role.
|
||||
*
|
||||
* @throws dml_exception
|
||||
*/
|
||||
public static function get_site_dpos() {
|
||||
// Get role(s) that can manage data requests.
|
||||
$dporoles = explode(',', get_config('tool_dataprivacy', 'dporoles'));
|
||||
|
||||
$dpos = [];
|
||||
$context = context_system::instance();
|
||||
foreach ($dporoles as $roleid) {
|
||||
if (empty($roleid)) {
|
||||
continue;
|
||||
}
|
||||
$allnames = get_all_user_name_fields(true, 'u');
|
||||
$fields = 'u.id, u.confirmed, u.username, '. $allnames . ', ' .
|
||||
'u.maildisplay, u.mailformat, u.maildigest, u.email, u.emailstop, u.city, '.
|
||||
'u.country, u.picture, u.idnumber, u.department, u.institution, '.
|
||||
'u.lang, u.timezone, u.lastaccess, u.mnethostid, u.auth, u.suspended, u.deleted, ' .
|
||||
'r.name AS rolename, r.sortorder, '.
|
||||
'r.shortname AS roleshortname, rn.name AS rolecoursealias';
|
||||
// Fetch users that can manage data requests.
|
||||
$dpos += get_role_users($roleid, $context, false, $fields);
|
||||
}
|
||||
|
||||
// If the site has no data protection officer, defer to site admin(s).
|
||||
if (empty($dpos)) {
|
||||
$dpos = get_admins();
|
||||
}
|
||||
return $dpos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given user is a site DPO.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
* @return bool
|
||||
* @throws dml_exception
|
||||
*/
|
||||
public static function is_site_dpo($userid) {
|
||||
$dpos = self::get_site_dpos();
|
||||
return array_key_exists($userid, $dpos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lodges a data request and sends the request details to the site Data Protection Officer(s).
|
||||
*
|
||||
* @param int $foruser The user whom the request is being made for.
|
||||
* @param int $type The request type.
|
||||
* @param string $comments Request comments.
|
||||
* @return data_request
|
||||
* @throws invalid_persistent_exception
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public static function create_data_request($foruser, $type, $comments = '') {
|
||||
global $USER;
|
||||
|
||||
$datarequest = new data_request();
|
||||
// The user the request is being made for.
|
||||
$datarequest->set('userid', $foruser);
|
||||
|
||||
$requestinguser = $USER->id;
|
||||
// Check when the user is making a request on behalf of another.
|
||||
if ($requestinguser != $foruser) {
|
||||
if (self::is_site_dpo($requestinguser)) {
|
||||
// The user making the request is a DPO. Should be fine.
|
||||
$datarequest->set('dpo', $requestinguser);
|
||||
} else {
|
||||
// If not a DPO, only users with the capability to make data requests for the user should be allowed.
|
||||
// (e.g. users with the Parent role, etc).
|
||||
if (!api::can_create_data_request_for_user($foruser)) {
|
||||
$forusercontext = \context_user::instance($foruser);
|
||||
throw new required_capability_exception($forusercontext,
|
||||
'tool/dataprivacy:makedatarequestsforchildren', 'nopermissions', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
// The user making the request.
|
||||
$datarequest->set('requestedby', $requestinguser);
|
||||
// Set status.
|
||||
$datarequest->set('status', self::DATAREQUEST_STATUS_PENDING);
|
||||
// Set request type.
|
||||
$datarequest->set('type', $type);
|
||||
// Set request comments.
|
||||
$datarequest->set('comments', $comments);
|
||||
|
||||
// Store subject access request.
|
||||
$datarequest->create();
|
||||
|
||||
// Fire an ad hoc task to initiate the data request process.
|
||||
$task = new initiate_data_request_task();
|
||||
$task->set_custom_data(['requestid' => $datarequest->get('id')]);
|
||||
manager::queue_adhoc_task($task, true);
|
||||
|
||||
return $datarequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the list of the data requests.
|
||||
*
|
||||
* If user ID is provided, it fetches the data requests for the user.
|
||||
* Otherwise, it fetches all of the data requests, provided that the user has the capability to manage data requests.
|
||||
* (e.g. Users with the Data Protection Officer roles)
|
||||
*
|
||||
* @param int $userid The User ID.
|
||||
* @return data_request[]
|
||||
* @throws dml_exception
|
||||
*/
|
||||
public static function get_data_requests($userid = 0) {
|
||||
global $DB, $USER;
|
||||
$results = [];
|
||||
$sort = 'status ASC, timemodified ASC';
|
||||
if ($userid) {
|
||||
// Get the data requests for the user or data requests made by the user.
|
||||
$select = "(userid = :userid OR requestedby = :requestedby)";
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
'requestedby' => $userid
|
||||
];
|
||||
|
||||
// Build a list of user IDs that the user is allowed to make data requests for.
|
||||
// Of course, the user should be included in this list.
|
||||
$alloweduserids = [$userid];
|
||||
// Get any users that the user can make data requests for.
|
||||
if ($children = helper::get_children_of_user($userid)) {
|
||||
// Get the list of user IDs of the children and merge to the allowed user IDs.
|
||||
$alloweduserids = array_merge($alloweduserids, array_keys($children));
|
||||
}
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($alloweduserids, SQL_PARAMS_NAMED);
|
||||
$select .= " AND userid $insql";
|
||||
$params = array_merge($params, $inparams);
|
||||
|
||||
$results = data_request::get_records_select($select, $params, $sort);
|
||||
} else {
|
||||
// If the current user is one of the site's Data Protection Officers, then fetch all data requests.
|
||||
if (self::is_site_dpo($USER->id)) {
|
||||
$results = data_request::get_records(null, $sort, '');
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there is already an existing pending/in-progress data request for a user for a given request type.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
* @param int $type The request type.
|
||||
* @return bool
|
||||
* @throws coding_exception
|
||||
* @throws dml_exception
|
||||
*/
|
||||
public static function has_ongoing_request($userid, $type) {
|
||||
global $DB;
|
||||
|
||||
// Check if the user already has an incomplete data request of the same type.
|
||||
$nonpendingstatuses = [
|
||||
self::DATAREQUEST_STATUS_COMPLETE,
|
||||
self::DATAREQUEST_STATUS_CANCELLED,
|
||||
self::DATAREQUEST_STATUS_REJECTED,
|
||||
];
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($nonpendingstatuses, SQL_PARAMS_NAMED);
|
||||
$select = 'type = :type AND userid = :userid AND status NOT ' . $insql;
|
||||
$params = array_merge([
|
||||
'type' => $type,
|
||||
'userid' => $userid
|
||||
], $inparams);
|
||||
|
||||
return data_request::record_exists_select($select, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a request is active or not based on its status.
|
||||
*
|
||||
* @param int $status The request status.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_active($status) {
|
||||
// List of statuses which doesn't require any further processing.
|
||||
$finalstatuses = [
|
||||
self::DATAREQUEST_STATUS_COMPLETE,
|
||||
self::DATAREQUEST_STATUS_CANCELLED,
|
||||
self::DATAREQUEST_STATUS_REJECTED,
|
||||
];
|
||||
|
||||
return !in_array($status, $finalstatuses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the data request for a given request ID.
|
||||
*
|
||||
* @param int $requestid The request identifier.
|
||||
* @param int $status The request status.
|
||||
* @param int $dpoid The user ID of the Data Protection Officer
|
||||
* @param string $comment The comment about the status update.
|
||||
* @return bool
|
||||
* @throws invalid_persistent_exception
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public static function update_request_status($requestid, $status, $dpoid = 0, $comment = '') {
|
||||
// Update the request.
|
||||
$datarequest = new data_request($requestid);
|
||||
$datarequest->set('status', $status);
|
||||
if ($dpoid) {
|
||||
$datarequest->set('dpo', $dpoid);
|
||||
}
|
||||
$datarequest->set('dpocomment', $comment);
|
||||
return $datarequest->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a request based on the request ID.
|
||||
*
|
||||
* @param int $requestid The request identifier
|
||||
* @return data_request
|
||||
*/
|
||||
public static function get_request($requestid) {
|
||||
return new data_request($requestid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approves a data request based on the request ID.
|
||||
*
|
||||
* @param int $requestid The request identifier
|
||||
* @return bool
|
||||
* @throws coding_exception
|
||||
* @throws dml_exception
|
||||
* @throws invalid_persistent_exception
|
||||
* @throws required_capability_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function approve_data_request($requestid) {
|
||||
global $USER;
|
||||
|
||||
// Check first whether the user can manage data requests.
|
||||
if (!self::can_manage_data_requests($USER->id)) {
|
||||
$context = context_system::instance();
|
||||
throw new required_capability_exception($context, 'tool/dataprivacy:managedatarequests', 'nopermissions', '');
|
||||
}
|
||||
|
||||
// Check if request is already awaiting for approval.
|
||||
$request = new data_request($requestid);
|
||||
if ($request->get('status') != self::DATAREQUEST_STATUS_AWAITING_APPROVAL) {
|
||||
throw new moodle_exception('errorrequestnotwaitingforapproval', 'tool_dataprivacy');
|
||||
}
|
||||
|
||||
// Update the status and the DPO.
|
||||
$result = self::update_request_status($requestid, self::DATAREQUEST_STATUS_APPROVED, $USER->id);
|
||||
|
||||
// Approve all the contexts attached to the request.
|
||||
// Currently, approving the request implicitly approves all associated contexts, but this may change in future, allowing
|
||||
// users to selectively approve certain contexts only.
|
||||
self::update_request_contexts_with_status($requestid, contextlist_context::STATUS_APPROVED);
|
||||
|
||||
// Fire an ad hoc task to initiate the data request process.
|
||||
$task = new process_data_request_task();
|
||||
$task->set_custom_data(['requestid' => $requestid]);
|
||||
if ($request->get('type') == self::DATAREQUEST_TYPE_EXPORT) {
|
||||
$task->set_userid($request->get('userid'));
|
||||
}
|
||||
manager::queue_adhoc_task($task, true);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects a data request based on the request ID.
|
||||
*
|
||||
* @param int $requestid The request identifier
|
||||
* @return bool
|
||||
* @throws coding_exception
|
||||
* @throws dml_exception
|
||||
* @throws invalid_persistent_exception
|
||||
* @throws required_capability_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function deny_data_request($requestid) {
|
||||
global $USER;
|
||||
|
||||
if (!self::can_manage_data_requests($USER->id)) {
|
||||
$context = context_system::instance();
|
||||
throw new required_capability_exception($context, 'tool/dataprivacy:managedatarequests', 'nopermissions', '');
|
||||
}
|
||||
|
||||
// Check if request is already awaiting for approval.
|
||||
$request = new data_request($requestid);
|
||||
if ($request->get('status') != self::DATAREQUEST_STATUS_AWAITING_APPROVAL) {
|
||||
throw new moodle_exception('errorrequestnotwaitingforapproval', 'tool_dataprivacy');
|
||||
}
|
||||
|
||||
// Update the status and the DPO.
|
||||
return self::update_request_status($requestid, self::DATAREQUEST_STATUS_REJECTED, $USER->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the site's Data Protection Officer about a request.
|
||||
*
|
||||
* @param stdClass $dpo The DPO user record
|
||||
* @param data_request $request The data request
|
||||
* @return int|false
|
||||
* @throws coding_exception
|
||||
* @throws dml_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function notify_dpo($dpo, data_request $request) {
|
||||
global $PAGE, $SITE;
|
||||
|
||||
$output = $PAGE->get_renderer('tool_dataprivacy');
|
||||
|
||||
$usercontext = \context_user::instance($request->get('requestedby'));
|
||||
$requestexporter = new data_request_exporter($request, ['context' => $usercontext]);
|
||||
$requestdata = $requestexporter->export($output);
|
||||
|
||||
// Create message to send to the Data Protection Officer(s).
|
||||
$typetext = null;
|
||||
$typetext = $requestdata->typename;
|
||||
$subject = get_string('datarequestemailsubject', 'tool_dataprivacy', $typetext);
|
||||
|
||||
$requestedby = $requestdata->requestedbyuser;
|
||||
$datarequestsurl = new moodle_url('/admin/tool/dataprivacy/datarequests.php');
|
||||
$message = new message();
|
||||
$message->courseid = $SITE->id;
|
||||
$message->component = 'tool_dataprivacy';
|
||||
$message->name = 'contactdataprotectionofficer';
|
||||
$message->userfrom = $requestedby->id;
|
||||
$message->replyto = $requestedby->email;
|
||||
$message->replytoname = $requestedby->fullname;
|
||||
$message->subject = $subject;
|
||||
$message->fullmessageformat = FORMAT_HTML;
|
||||
$message->notification = 1;
|
||||
$message->contexturl = $datarequestsurl;
|
||||
$message->contexturlname = get_string('datarequests', 'tool_dataprivacy');
|
||||
|
||||
// Prepare the context data for the email message body.
|
||||
$messagetextdata = [
|
||||
'requestedby' => $requestedby->fullname,
|
||||
'requesttype' => $typetext,
|
||||
'requestdate' => userdate($requestdata->timecreated),
|
||||
'requestcomments' => $requestdata->messagehtml,
|
||||
'datarequestsurl' => $datarequestsurl
|
||||
];
|
||||
$requestingfor = $requestdata->foruser;
|
||||
if ($requestedby->id == $requestingfor->id) {
|
||||
$messagetextdata['requestfor'] = $messagetextdata['requestedby'];
|
||||
} else {
|
||||
$messagetextdata['requestfor'] = $requestingfor->fullname;
|
||||
}
|
||||
|
||||
// Email the data request to the Data Protection Officer(s)/Admin(s).
|
||||
$messagetextdata['dponame'] = fullname($dpo);
|
||||
// Render message email body.
|
||||
$messagehtml = $output->render_from_template('tool_dataprivacy/data_request_email', $messagetextdata);
|
||||
$message->userto = $dpo;
|
||||
$message->fullmessage = html_to_text($messagehtml);
|
||||
$message->fullmessagehtml = $messagehtml;
|
||||
|
||||
// Send message.
|
||||
return message_send($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a non-DPO user can make a data request for another user.
|
||||
*
|
||||
* @param int $user The user ID of the target user.
|
||||
* @param int $requester The user ID of the user making the request.
|
||||
* @return bool
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public static function can_create_data_request_for_user($user, $requester = null) {
|
||||
$usercontext = \context_user::instance($user);
|
||||
return has_capability('tool/dataprivacy:makedatarequestsforchildren', $usercontext, $requester);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new data purpose.
|
||||
*
|
||||
* @param stdClass $record
|
||||
* @return \tool_dataprivacy\purpose.
|
||||
*/
|
||||
public static function create_purpose(stdClass $record) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$purpose = new purpose(0, $record);
|
||||
$purpose->create();
|
||||
|
||||
return $purpose;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing data purpose.
|
||||
*
|
||||
* @param stdClass $record
|
||||
* @return \tool_dataprivacy\purpose.
|
||||
*/
|
||||
public static function update_purpose(stdClass $record) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
if (!isset($record->sensitivedatareasons)) {
|
||||
$record->sensitivedatareasons = '';
|
||||
}
|
||||
|
||||
$purpose = new purpose($record->id);
|
||||
$purpose->from_record($record);
|
||||
|
||||
$result = $purpose->update();
|
||||
|
||||
return $purpose;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a data purpose.
|
||||
*
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public static function delete_purpose($id) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$purpose = new purpose($id);
|
||||
if ($purpose->is_used()) {
|
||||
throw new \moodle_exception('Purpose with id ' . $id . ' can not be deleted because it is used.');
|
||||
}
|
||||
return $purpose->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all system data purposes.
|
||||
*
|
||||
* @return \tool_dataprivacy\purpose[]
|
||||
*/
|
||||
public static function get_purposes() {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
return purpose::get_records([], 'name', 'ASC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new data category.
|
||||
*
|
||||
* @param stdClass $record
|
||||
* @return \tool_dataprivacy\category.
|
||||
*/
|
||||
public static function create_category(stdClass $record) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$category = new category(0, $record);
|
||||
$category->create();
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing data category.
|
||||
*
|
||||
* @param stdClass $record
|
||||
* @return \tool_dataprivacy\category.
|
||||
*/
|
||||
public static function update_category(stdClass $record) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$category = new category($record->id);
|
||||
$category->from_record($record);
|
||||
|
||||
$result = $category->update();
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a data category.
|
||||
*
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public static function delete_category($id) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$category = new category($id);
|
||||
if ($category->is_used()) {
|
||||
throw new \moodle_exception('Category with id ' . $id . ' can not be deleted because it is used.');
|
||||
}
|
||||
return $category->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all system data categories.
|
||||
*
|
||||
* @return \tool_dataprivacy\category[]
|
||||
*/
|
||||
public static function get_categories() {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
return category::get_records([], 'name', 'ASC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the context instance purpose and category.
|
||||
*
|
||||
* @param \stdClass $record
|
||||
* @return \tool_dataprivacy\context_instance
|
||||
*/
|
||||
public static function set_context_instance($record) {
|
||||
self::check_can_manage_data_registry($record->contextid);
|
||||
|
||||
if ($instance = context_instance::get_record_by_contextid($record->contextid, false)) {
|
||||
// Update.
|
||||
$instance->from_record($record);
|
||||
|
||||
if (empty($record->purposeid) && empty($record->categoryid)) {
|
||||
// We accept one of them to be null but we delete it if both are null.
|
||||
self::unset_context_instance($instance);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Add.
|
||||
$instance = new context_instance(0, $record);
|
||||
}
|
||||
$instance->save();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets the context instance record.
|
||||
*
|
||||
* @param \tool_dataprivacy\context_instance $instance
|
||||
* @return null
|
||||
*/
|
||||
public static function unset_context_instance(context_instance $instance) {
|
||||
self::check_can_manage_data_registry($instance->get('contextid'));
|
||||
$instance->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the context level purpose and category.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
* @param \stdClass $record
|
||||
* @return contextlevel
|
||||
*/
|
||||
public static function set_contextlevel($record) {
|
||||
global $DB;
|
||||
|
||||
// Only manager at system level can set this.
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
if ($record->contextlevel != CONTEXT_SYSTEM && $record->contextlevel != CONTEXT_USER) {
|
||||
throw new \coding_exception('Only context system and context user can set a contextlevel ' .
|
||||
'purpose and retention');
|
||||
}
|
||||
|
||||
if ($contextlevel = contextlevel::get_record_by_contextlevel($record->contextlevel, false)) {
|
||||
// Update.
|
||||
$contextlevel->from_record($record);
|
||||
} else {
|
||||
// Add.
|
||||
$contextlevel = new contextlevel(0, $record);
|
||||
}
|
||||
$contextlevel->save();
|
||||
|
||||
// We sync with their defaults as we removed these options from the defaults page.
|
||||
$classname = \context_helper::get_class_for_level($record->contextlevel);
|
||||
list($purposevar, $categoryvar) = data_registry::var_names_from_context($classname);
|
||||
set_config($purposevar, $record->purposeid, 'tool_dataprivacy');
|
||||
set_config($categoryvar, $record->categoryid, 'tool_dataprivacy');
|
||||
|
||||
return $contextlevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective category given a context instance.
|
||||
*
|
||||
* @param \context $context
|
||||
* @param int $forcedvalue Use this categoryid value as if this was this context instance category.
|
||||
* @return category|false
|
||||
*/
|
||||
public static function get_effective_context_category(\context $context, $forcedvalue=false) {
|
||||
self::check_can_manage_data_registry($context->id);
|
||||
if (!data_registry::defaults_set()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return data_registry::get_effective_context_value($context, 'category', $forcedvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective purpose given a context instance.
|
||||
*
|
||||
* @param \context $context
|
||||
* @param int $forcedvalue Use this purposeid value as if this was this context instance purpose.
|
||||
* @return purpose|false
|
||||
*/
|
||||
public static function get_effective_context_purpose(\context $context, $forcedvalue=false) {
|
||||
self::check_can_manage_data_registry($context->id);
|
||||
if (!data_registry::defaults_set()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return data_registry::get_effective_context_value($context, 'purpose', $forcedvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective category given a context level.
|
||||
*
|
||||
* @param int $contextlevel
|
||||
* @param int $forcedvalue Use this categoryid value as if this was this context level category.
|
||||
* @return category|false
|
||||
*/
|
||||
public static function get_effective_contextlevel_category($contextlevel, $forcedvalue=false) {
|
||||
self::check_can_manage_data_registry(\context_system::instance()->id);
|
||||
if (!data_registry::defaults_set()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return data_registry::get_effective_contextlevel_value($contextlevel, 'category', $forcedvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective purpose given a context level.
|
||||
*
|
||||
* @param int $contextlevel
|
||||
* @param int $forcedvalue Use this purposeid value as if this was this context level purpose.
|
||||
* @return purpose|false
|
||||
*/
|
||||
public static function get_effective_contextlevel_purpose($contextlevel, $forcedvalue=false) {
|
||||
self::check_can_manage_data_registry(\context_system::instance()->id);
|
||||
if (!data_registry::defaults_set()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return data_registry::get_effective_contextlevel_value($contextlevel, 'purpose', $forcedvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an expired context record for the provided context id.
|
||||
*
|
||||
* @param int $contextid
|
||||
* @return \tool_dataprivacy\expired_context
|
||||
*/
|
||||
public static function create_expired_context($contextid) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$record = (object)[
|
||||
'contextid' => $contextid,
|
||||
'status' => expired_context::STATUS_EXPIRED,
|
||||
];
|
||||
$expiredctx = new expired_context(0, $record);
|
||||
$expiredctx->save();
|
||||
|
||||
return $expiredctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an expired context record.
|
||||
*
|
||||
* @param int $id The tool_dataprivacy_ctxexpire id.
|
||||
* @return bool True on success.
|
||||
*/
|
||||
public static function delete_expired_context($id) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$expiredcontext = new expired_context($id);
|
||||
return $expiredcontext->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of an expired context.
|
||||
*
|
||||
* @param \tool_dataprivacy\expired_context $expiredctx
|
||||
* @param int $status
|
||||
* @return null
|
||||
*/
|
||||
public static function set_expired_context_status(expired_context $expiredctx, $status) {
|
||||
self::check_can_manage_data_registry();
|
||||
|
||||
$expiredctx->set('status', $status);
|
||||
$expiredctx->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the contexts from the contextlist_collection to the request with the status provided.
|
||||
*
|
||||
* @param contextlist_collection $clcollection a collection of contextlists for all components.
|
||||
* @param int $requestid the id of the request.
|
||||
* @param int $status the status to set the contexts to.
|
||||
*/
|
||||
public static function add_request_contexts_with_status(contextlist_collection $clcollection, int $requestid, int $status) {
|
||||
$request = new data_request($requestid);
|
||||
foreach ($clcollection as $contextlist) {
|
||||
// Convert the \core_privacy\local\request\contextlist into a contextlist persistent and store it.
|
||||
$clp = \tool_dataprivacy\contextlist::from_contextlist($contextlist);
|
||||
$clp->create();
|
||||
$contextlistid = $clp->get('id');
|
||||
|
||||
// Store the associated contexts in the contextlist.
|
||||
foreach ($contextlist->get_contextids() as $contextid) {
|
||||
if ($request->get('type') == static::DATAREQUEST_TYPE_DELETE) {
|
||||
$context = \context::instance_by_id($contextid);
|
||||
if (($purpose = static::get_effective_context_purpose($context)) && !empty($purpose->get('protected'))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$context = new contextlist_context();
|
||||
$context->set('contextid', $contextid)
|
||||
->set('contextlistid', $contextlistid)
|
||||
->set('status', $status)
|
||||
->create();
|
||||
}
|
||||
|
||||
// Create the relation to the request.
|
||||
$requestcontextlist = request_contextlist::create_relation($requestid, $contextlistid);
|
||||
$requestcontextlist->create();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status of all contexts associated with the request.
|
||||
*
|
||||
* @param int $requestid the requestid to which the contexts belong.
|
||||
* @param int $status the status to set to.
|
||||
* @throws \dml_exception if the requestid is invalid.
|
||||
* @throws \moodle_exception if the status is invalid.
|
||||
*/
|
||||
public static function update_request_contexts_with_status(int $requestid, int $status) {
|
||||
// Validate contextlist_context status using the persistent's attribute validation.
|
||||
$contextlistcontext = new contextlist_context();
|
||||
$contextlistcontext->set('status', $status);
|
||||
if (array_key_exists('status', $contextlistcontext->get_errors())) {
|
||||
throw new moodle_exception("Invalid contextlist_context status: $status");
|
||||
}
|
||||
|
||||
// Validate requestid using the persistent's record validation.
|
||||
// A dml_exception is thrown if the record is missing.
|
||||
$datarequest = new data_request($requestid);
|
||||
|
||||
// Bulk update the status of the request contexts.
|
||||
global $DB;
|
||||
|
||||
$select = "SELECT ctx.id as id
|
||||
FROM {" . request_contextlist::TABLE . "} rcl
|
||||
JOIN {" . contextlist::TABLE . "} cl ON rcl.contextlistid = cl.id
|
||||
JOIN {" . contextlist_context::TABLE . "} ctx ON cl.id = ctx.contextlistid
|
||||
WHERE rcl.requestid = ?";
|
||||
|
||||
// Fetch records IDs to be updated and update by chunks, if applicable (limit of 1000 records per update).
|
||||
$limit = 1000;
|
||||
$idstoupdate = $DB->get_fieldset_sql($select, [$requestid]);
|
||||
$count = count($idstoupdate);
|
||||
$idchunks = $idstoupdate;
|
||||
if ($count > $limit) {
|
||||
$idchunks = array_chunk($idstoupdate, $limit);
|
||||
}
|
||||
$transaction = $DB->start_delegated_transaction();
|
||||
$initialparams = [$status];
|
||||
foreach ($idchunks as $chunk) {
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($chunk);
|
||||
$update = "UPDATE {" . contextlist_context::TABLE . "}
|
||||
SET status = ?
|
||||
WHERE id $insql";
|
||||
$params = array_merge($initialparams, $inparams);
|
||||
$DB->execute($update, $params);
|
||||
}
|
||||
$transaction->allow_commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all request contextlists having at least on approved context, and returns them as in a contextlist_collection.
|
||||
*
|
||||
* @param data_request $request the data request with which the contextlists are associated.
|
||||
* @return contextlist_collection the collection of approved_contextlist objects.
|
||||
*/
|
||||
public static function get_approved_contextlist_collection_for_request(data_request $request) : contextlist_collection {
|
||||
$foruser = core_user::get_user($request->get('userid'));
|
||||
|
||||
// Fetch all approved contextlists and create the core_privacy\local\request\contextlist objects here.
|
||||
global $DB;
|
||||
$sql = "SELECT cl.component, ctx.contextid
|
||||
FROM {" . request_contextlist::TABLE . "} rcl
|
||||
JOIN {" . contextlist::TABLE . "} cl ON rcl.contextlistid = cl.id
|
||||
JOIN {" . contextlist_context::TABLE . "} ctx ON cl.id = ctx.contextlistid
|
||||
WHERE rcl.requestid = ?
|
||||
AND ctx.status = ?
|
||||
ORDER BY cl.component, ctx.contextid";
|
||||
|
||||
// Create the approved contextlist collection object.
|
||||
$lastcomponent = null;
|
||||
$approvedcollection = new contextlist_collection($foruser->id);
|
||||
|
||||
$rs = $DB->get_recordset_sql($sql, [$request->get('id'), contextlist_context::STATUS_APPROVED]);
|
||||
foreach ($rs as $record) {
|
||||
// If we encounter a new component, and we've built up contexts for the last, then add the approved_contextlist for the
|
||||
// last (the one we've just finished with) and reset the context array for the next one.
|
||||
if ($lastcomponent != $record->component) {
|
||||
if (!empty($contexts)) {
|
||||
$approvedcollection->add_contextlist(new approved_contextlist($foruser, $lastcomponent, $contexts));
|
||||
}
|
||||
$contexts = [];
|
||||
}
|
||||
|
||||
$contexts[] = $record->contextid;
|
||||
$lastcomponent = $record->component;
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
// The data for the last component contextlist won't have been written yet, so write it now.
|
||||
if (!empty($contexts)) {
|
||||
$approvedcollection->add_contextlist(new approved_contextlist($foruser, $lastcomponent, $contexts));
|
||||
}
|
||||
|
||||
return $approvedcollection;
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Class for loading/storing data categories from the DB.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_dataprivacy;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/dataprivacy/lib.php');
|
||||
|
||||
/**
|
||||
* Class for loading/storing data categories from the DB.
|
||||
*
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class category extends \core\persistent {
|
||||
|
||||
/**
|
||||
* Database table.
|
||||
*/
|
||||
const TABLE = 'tool_dataprivacy_category';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'name' => array(
|
||||
'type' => PARAM_TEXT,
|
||||
'description' => 'The category name.',
|
||||
),
|
||||
'description' => array(
|
||||
'type' => PARAM_RAW,
|
||||
'description' => 'The category description.',
|
||||
'null' => NULL_ALLOWED,
|
||||
'default' => '',
|
||||
),
|
||||
'descriptionformat' => array(
|
||||
'choices' => array(FORMAT_HTML, FORMAT_MOODLE, FORMAT_PLAIN, FORMAT_MARKDOWN),
|
||||
'type' => PARAM_INT,
|
||||
'default' => FORMAT_HTML
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this category used?.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function is_used() {
|
||||
|
||||
if (\tool_dataprivacy\contextlevel::is_category_used($this->get('id')) ||
|
||||
\tool_dataprivacy\context_instance::is_category_used($this->get('id'))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$pluginconfig = get_config('tool_dataprivacy');
|
||||
$levels = \context_helper::get_all_levels();
|
||||
foreach ($levels as $level => $classname) {
|
||||
|
||||
list($unused, $categoryvar) = \tool_dataprivacy\data_registry::var_names_from_context($classname);
|
||||
if (!empty($pluginconfig->{$categoryvar}) && $pluginconfig->{$categoryvar} == $this->get('id')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Class for loading/storing context instances data from the DB.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_dataprivacy;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class for loading/storing context instances data from the DB.
|
||||
*
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class context_instance extends \core\persistent {
|
||||
|
||||
/**
|
||||
* Database table.
|
||||
*/
|
||||
const TABLE = 'tool_dataprivacy_ctxinstance';
|
||||
|
||||
/**
|
||||
* Not set value.
|
||||
*/
|
||||
const NOTSET = 0;
|
||||
|
||||
/**
|
||||
* Inherit value.
|
||||
*/
|
||||
const INHERIT = -1;
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'contextid' => array(
|
||||
'type' => PARAM_INT,
|
||||
'description' => 'The context id.',
|
||||
),
|
||||
'purposeid' => array(
|
||||
'type' => PARAM_INT,
|
||||
'description' => 'The purpose id.',
|
||||
'null' => NULL_ALLOWED,
|
||||
),
|
||||
'categoryid' => array(
|
||||
'type' => PARAM_INT,
|
||||
'description' => 'The category id.',
|
||||
'null' => NULL_ALLOWED,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance by contextid.
|
||||
*
|
||||
* @param mixed $contextid
|
||||
* @param mixed $exception
|
||||
* @return null
|
||||
*/
|
||||
public static function get_record_by_contextid($contextid, $exception = true) {
|
||||
global $DB;
|
||||
|
||||
if (!$record = $DB->get_record(self::TABLE, array('contextid' => $contextid))) {
|
||||
if (!$exception) {
|
||||
return false;
|
||||
} else {
|
||||
throw new \dml_missing_record_exception(self::TABLE);
|
||||
}
|
||||
}
|
||||
|
||||
return new static(0, $record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the provided purpose used by any context instance?
|
||||
*
|
||||
* @param int $purposeid
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_purpose_used($purposeid) {
|
||||
global $DB;
|
||||
return $DB->record_exists(self::TABLE, array('purposeid' => $purposeid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the provided category used by any context instance?
|
||||
*
|
||||
* @param int $categoryid
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_category_used($categoryid) {
|
||||
global $DB;
|
||||
return $DB->record_exists(self::TABLE, array('categoryid' => $categoryid));
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Class for loading/storing context level data from the DB.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_dataprivacy;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class for loading/storing context level data from the DB.
|
||||
*
|
||||
* @copyright 2018 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlevel extends \core\persistent {
|
||||
|
||||
/**
|
||||
* Database table.
|
||||
*/
|
||||
const TABLE = 'tool_dataprivacy_ctxlevel';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'contextlevel' => array(
|
||||
'type' => PARAM_INT,
|
||||
'description' => 'The context level.',
|
||||
),
|
||||
'purposeid' => array(
|
||||
'type' => PARAM_INT,
|
||||
'description' => 'The purpose id.',
|
||||
),
|
||||
'categoryid' => array(
|
||||
'type' => PARAM_INT,
|
||||
'description' => 'The category id.',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance by contextlevel.
|
||||
*
|
||||
* @param mixed $contextlevel
|
||||
* @param mixed $exception
|
||||
* @return null
|
||||
*/
|
||||
public static function get_record_by_contextlevel($contextlevel, $exception = true) {
|
||||
global $DB;
|
||||
|
||||
$cache = \cache::make('tool_dataprivacy', 'contextlevel');
|
||||
if ($data = $cache->get($contextlevel)) {
|
||||
return new static(0, $data);
|
||||
}
|
||||
|
||||
if (!$record = $DB->get_record(self::TABLE, array('contextlevel' => $contextlevel))) {
|
||||
if (!$exception) {
|
||||
return false;
|
||||
} else {
|
||||
throw new \dml_missing_record_exception(self::TABLE);
|
||||
}
|
||||
}
|
||||
|
||||
return new static(0, $record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the provided purpose used by any contextlevel?
|
||||
*
|
||||
* @param int $purposeid
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_purpose_used($purposeid) {
|
||||
global $DB;
|
||||
return $DB->record_exists(self::TABLE, array('purposeid' => $purposeid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the provided category used by any contextlevel?
|
||||
*
|
||||
* @param int $categoryid
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_category_used($categoryid) {
|
||||
global $DB;
|
||||
return $DB->record_exists(self::TABLE, array('categoryid' => $categoryid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the new record to the cache.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
protected function after_create() {
|
||||
$cache = \cache::make('tool_dataprivacy', 'contextlevel');
|
||||
$cache->set($this->get('contextlevel'), $this->to_record());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the cache record.
|
||||
*
|
||||
* @param bool $result
|
||||
* @return null
|
||||
*/
|
||||
protected function after_update($result) {
|
||||
$cache = \cache::make('tool_dataprivacy', 'contextlevel');
|
||||
$cache->set($this->get('contextlevel'), $this->to_record());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes unnecessary stuff from db.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
protected function before_delete() {
|
||||
$cache = \cache::make('tool_dataprivacy', 'contextlevel');
|
||||
$cache->delete($this->get('contextlevel'));
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Contains the contextlist persistent.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_dataprivacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\persistent;
|
||||
|
||||
/**
|
||||
* The contextlist persistent.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlist extends persistent {
|
||||
|
||||
/** The table name this persistent object maps to. */
|
||||
const TABLE = 'tool_dataprivacy_contextlist';
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return [
|
||||
'component' => [
|
||||
'type' => PARAM_TEXT
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new contextlist persistent from an instance of \core_privacy\local\request\contextlist.
|
||||
*
|
||||
* @param \core_privacy\local\request\contextlist $contextlist the core privacy contextlist.
|
||||
* @return contextlist a contextlist persistent.
|
||||
*/
|
||||
public static function from_contextlist(\core_privacy\local\request\contextlist $contextlist) : contextlist {
|
||||
$contextlistpersistent = new contextlist();
|
||||
return $contextlistpersistent->set('component', $contextlist->get_component());
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Contains the contextlist_context persistent.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_dataprivacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\persistent;
|
||||
|
||||
/**
|
||||
* The contextlist_context persistent.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class contextlist_context extends persistent {
|
||||
|
||||
/** The table name this persistent object maps to. */
|
||||
const TABLE = 'tool_dataprivacy_ctxlst_ctx';
|
||||
|
||||
/** This context is pending approval. */
|
||||
const STATUS_PENDING = 0;
|
||||
|
||||
/** This context has been approved. */
|
||||
const STATUS_APPROVED = 1;
|
||||
|
||||
/** This context has been rejected. */
|
||||
const STATUS_REJECTED = 2;
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return [
|
||||
'contextid' => [
|
||||
'type' => PARAM_INT
|
||||
],
|
||||
'contextlistid' => [
|
||||
'type' => PARAM_INT
|
||||
],
|
||||
'status' => [
|
||||
'choices' => [
|
||||
self::STATUS_PENDING,
|
||||
self::STATUS_APPROVED,
|
||||
self::STATUS_REJECTED,
|
||||
],
|
||||
'default' => self::STATUS_PENDING,
|
||||
'type' => PARAM_INT
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user