diff --git a/classes/admin_settingspage_tabs.php b/classes/admin_settingspage_tabs.php index ae571a8..aa05c8d 100644 --- a/classes/admin_settingspage_tabs.php +++ b/classes/admin_settingspage_tabs.php @@ -121,6 +121,7 @@ public function output_html() { break; } } + $context['privacynote'] = format_text(get_string('privacynote', 'theme_adaptable'), FORMAT_MARKDOWN); if ($CFG->branch != $this->mbranch) { $context['versioncheck'] = 'Release '.$plugininfo->release.', version '.$plugininfo->version.' is incompatible with Moodle '.$CFG->release; diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 0f66254..8565d91 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -15,32 +15,145 @@ // along with Moodle. If not, see . /** + * Adaptable theme. + * * Provider class file. As required for any data privacy information required. * - * @package theme_adaptable - * @copyright 2019 Manoj Solanki (Coventry University) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package theme_adaptable + * @copyright 2019 Manoj Solanki (Coventry University) + * @copyright 2023 G J Barnard. + * @author G J Barnard - + * {@link https://moodle.org/user/profile.php?id=442195} + * {@link https://gjbarnard.co.uk} + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later. */ -namespace theme_adaptable\privacy; + +namespace theme_foundation\privacy; + +use core_privacy\local\request\writer; +use core_privacy\local\metadata\collection; /** - * Provider class. - * - * @package theme_adaptable - * @copyright 2019 Manoj Solanki (Coventry University) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * Privacy provider. */ class provider implements - // This theme does not store any personal user data. - \core_privacy\local\metadata\null_provider { + // This plugin has data. + \core_privacy\local\metadata\provider, + + // This plugin has some sitewide user preferences to export. + \core_privacy\local\request\user_preference_provider { + + /** + * Returns meta data about this system. + * + * @param collection $items The initialised item collection to add items to. + * @return collection A listing of user data stored through this system. + */ + public static function get_metadata(collection $items): collection { + $items->add_user_preference('collapseblock', 'privacy:metadata:preference:collapseblock'); + $items->add_user_preference('drawer-open-index', 'privacy:metadata:preference:draweropenindex'); + $items->add_user_preference('drawer-open-block', 'privacy:metadata:preference:draweropenblock'); + $items->add_user_preference('theme_adaptable_zoom', 'privacy:metadata:preference:themeadaptablezoom'); + $items->add_user_preference('theme_adaptable_full', 'privacy:metadata:preference:themeadaptablefull'); + $items->add_user_preference('themeadaptablealertkey', 'privacy:metadata:preference:themeadaptablealertkey'); + return $items; + } /** - * Get the language string identifier with the component's language - * file to explain why this plugin stores no data. + * Store all user preferences for the plugin. * - * @return string + * @param int $userid The user id of the user whose data is to be exported. */ - public static function get_reason() : string { - return 'privacy:metadata'; + public static function export_user_preferences(int $userid) { + $preferences = get_user_preferences(null, null, $userid); + foreach ($preferences as $name => $value) { + $blockid = null; + $matches = []; + if (preg_match('/(?<=block)\d*(?=hidden)/', $name, $matches)) { + if (!empty($matches[0])) { + $blockid = $matches[0]; + $decoded = ($value) ? get_string('privacy:closed', 'theme_adaptable') : get_string('privacy:open', 'theme_adaptable'); + + writer::export_user_preference( + 'theme_adaptable', + $name, + $value, + get_string('privacy:request:preference:collapseblock', 'theme_adaptable', (object) [ + 'name' => $name, + 'blockid' => $blockid, + 'value' => $value, + 'decoded' => $decoded, + ]) + ); + } + } else if ($name == 'drawer-open-index') { + $decoded = ($value) ? get_string('privacy:closed', 'theme_adaptable') : get_string('privacy:open', 'theme_adaptable'); + + writer::export_user_preference( + 'theme_adaptable', + $name, + $value, + get_string('privacy:request:preference:draweropenindex', 'theme_adaptable', (object) [ + 'name' => $name, + 'value' => $value, + 'decoded' => $decoded, + ]) + ); + } else if ($name == 'drawer-open-block') { + $decoded = ($value) ? get_string('privacy:closed', 'theme_adaptable') : get_string('privacy:open', 'theme_adaptable'); + + writer::export_user_preference( + 'theme_adaptable', + $name, + $value, + get_string('privacy:request:preference:draweropenblock', 'theme_adaptable', (object) [ + 'name' => $name, + 'value' => $value, + 'decoded' => $decoded, + ]) + ); + } else if ($name == 'theme_adaptable_zoom') { + $decoded = ($value) ? get_string('privacy:closed', 'theme_adaptable') : get_string('privacy:open', 'theme_adaptable'); + + writer::export_user_preference( + 'theme_adaptable', + $name, + $value, + get_string('privacy:request:preference:themeadaptablezoom', 'theme_adaptable', (object) [ + 'name' => $name, + 'value' => $value, + 'decoded' => $decoded, + ]) + ); + } else if ($name == 'theme_adaptable_full') { + $decoded = get_string('privacy:'.$value, 'theme_adaptable'); + + writer::export_user_preference( + 'theme_adaptable', + $name, + $value, + get_string('privacy:request:preference:themeadaptablefull', 'theme_adaptable', (object) [ + 'name' => $name, + 'value' => $value, + 'decoded' => $decoded, + ]) + ); + } else if (preg_match('/(?<=theme_adaptable_alertkey)\d*/', $name, $matches)) { + if (!empty($matches[0])) { + $alertid = $matches[0]; + + writer::export_user_preference( + 'theme_adaptable', + $name, + $value, + get_string('privacy:request:preference:themeadaptablealertkey', 'theme_adaptable', (object) [ + 'name' => $name, + 'alertid' => $alertid, + 'value' => $value, + ]) + ); + } + } + } } } diff --git a/lang/en/theme_adaptable.php b/lang/en/theme_adaptable.php index 520afb1..fd6bab3 100644 --- a/lang/en/theme_adaptable.php +++ b/lang/en/theme_adaptable.php @@ -1728,7 +1728,23 @@ $string['putpropertiesignored'] = 'Ignored:'; // Privacy. -$string['privacy:metadata'] = 'Adaptable do not store any individual user data.'; +$string['privacynote'] = 'Note: The Adaptable theme has settings that pertain to its configuration. Specific user settings are described in the \'Plugin privacy registry\'. For the other settings, it is your responsibilty to ensure that no user data is entered in any of the free text fields. Setting a setting will result in that action being logged within the core Moodle logging system against the user whom changed it, this is outside of the themes control, please see the core logging system for privacy compliance for this. When uploading images, you should avoid uploading images with embedded location data (EXIF GPS) included or other such personal data. It would be possible to extract any location / personal data from the images. Please examine the code carefully to be sure that it complies with your interpretation of your privacy laws. I am not a lawyer and my analysis is based on my interpretation. If you have any doubt then remove the theme forthwith.'; +$string['privacy:closed'] = 'Closed'; +$string['privacy:open'] = 'Open'; +$string['privacy:nofull'] = 'Not full'; +$string['privacy:fullin'] = 'Full in'; +$string['privacy:metadata:preference:collapseblock'] = 'The state of the blocks on a page.'; +$string['privacy:request:preference:collapseblock'] = 'The user preference "{$a->name}" for block id "{$a->blockid}" has the value "{$a->value}" which represents "{$a->decoded}" for the state of the block.'; +$string['privacy:metadata:preference:draweropenindex'] = 'The state of the course index.'; +$string['privacy:request:preference:draweropenindex'] = 'The user preference "{$a->name}" has the value "{$a->value}" which represents "{$a->decoded}" for the state of the course index.'; +$string['privacy:metadata:preference:draweropenblock'] = 'The state of the block drawer.'; +$string['privacy:request:preference:draweropenblock'] = 'The user preference "{$a->name}" has the value "{$a->value}" which represents "{$a->decoded}" for the state of the block drawer.'; +$string['privacy:metadata:preference:themeadaptablezoom'] = 'The state of the zoom.'; +$string['privacy:request:preference:themeadaptablezoom'] = 'The user preference "{$a->name}" has the value "{$a->value}" which represents "{$a->decoded}" for the state of the zoom.'; +$string['privacy:metadata:preference:themeadaptablefull'] = 'The state of the full screen.'; +$string['privacy:request:preference:themeadaptablefull'] = 'The user preference "{$a->name}" has the value "{$a->value}" which represents "{$a->decoded}" for the state of the zoom.'; +$string['privacy:metadata:preference:themeadaptablealertkey'] = 'The state of the given alert.'; +$string['privacy:request:preference:themeadaptablealertkey'] = 'The user preference "{$a->name}" for alert id "{$a->alertid}" has the value "{$a->value}" for the given alert, \'undismissable\' or any other \'alertkey\' representing that the alert has been dismissed.'; // Adaptable Tabbed layout changes. $string['tabbedlayoutheading'] = 'Adaptable tabbed layout'; diff --git a/templates/adaptable_admin_setting_tabs.mustache b/templates/adaptable_admin_setting_tabs.mustache index eac9935..9bba5b2 100644 --- a/templates/adaptable_admin_setting_tabs.mustache +++ b/templates/adaptable_admin_setting_tabs.mustache @@ -23,6 +23,7 @@ "versioninfo": "Release 3.0.3, version 2020073104 on Moodle 3.9.4 (Build: 20210118)", "maturity": "Maturity info", "maturityalert": "info", + "privacynote": "Privacy info", "versioncheck": "Not supported on this version of Moodle", "tabs": [ { @@ -43,11 +44,13 @@ {{#maturity}}

{{versioninfo}}

-{{{maturity}}} +

{{{maturity}}}

+{{{privacynote}}}
{{/maturity}} {{^maturity}}

{{versioninfo}}

+{{privacynote}}} {{/maturity}} {{#versioncheck}}