diff --git a/mod/quiz/report/grading/classes/privacy/provider.php b/mod/quiz/report/grading/classes/privacy/provider.php new file mode 100644 index 0000000000000..bc5cae8deb518 --- /dev/null +++ b/mod/quiz/report/grading/classes/privacy/provider.php @@ -0,0 +1,46 @@ +. + +/** + * Privacy Subsystem implementation for quiz_grading. + * + * @package quiz_grading + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace quiz_grading\privacy; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Privacy Subsystem for quiz_grading implementing null_provider. + * + * @copyright 2018 Andrew Nicols + * @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'; + } +} diff --git a/mod/quiz/report/grading/lang/en/quiz_grading.php b/mod/quiz/report/grading/lang/en/quiz_grading.php index 2fda255e22ed2..6f53c956909cd 100644 --- a/mod/quiz/report/grading/lang/en/quiz_grading.php +++ b/mod/quiz/report/grading/lang/en/quiz_grading.php @@ -68,6 +68,7 @@ $string['options'] = 'Options'; $string['orderattempts'] = 'Order attempts'; $string['pluginname'] = 'Manual grading'; +$string['privacy:metadata'] = 'The Quiz Manual grading plugin does not store any personal data. It provides an interface for users to store data without storing any data itself.'; $string['qno'] = 'Q #'; $string['questionname'] = 'Question name'; $string['questionsperpage'] = 'Questions per page'; diff --git a/mod/quiz/report/overview/classes/privacy/provider.php b/mod/quiz/report/overview/classes/privacy/provider.php new file mode 100644 index 0000000000000..0f9fee4eab4b5 --- /dev/null +++ b/mod/quiz/report/overview/classes/privacy/provider.php @@ -0,0 +1,78 @@ +. + +/** + * Privacy Subsystem implementation for quiz_overview.. + * + * @package quiz_overview + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace quiz_overview\privacy; + +use \core_privacy\local\request\writer; +use \core_privacy\local\request\transform; +use \core_privacy\local\metadata\collection; +use \core_privacy\manager; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Privacy Subsystem implementation for quiz_overview.. + * + * @copyright 2018 Andrew Nicols + * @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('quiz_overview_slotmarks', 'privacy:metadata:preference:quiz_overview_slotmarks'); + + 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) { + $preference = get_user_preferences('quiz_overview_slotmarks', null); + if (null !== $preference) { + if (empty($preference)) { + $description = get_string('privacy:preference:slotmarks:no', 'quiz_overview'); + } else { + $description = get_string('privacy:preference:slotmarks:yes', 'quiz_overview'); + } + + writer::export_user_preference( + 'quiz_overview', + 'slotmarks', + transform::yesno($preference), + $description + ); + } + } +} diff --git a/mod/quiz/report/overview/lang/en/quiz_overview.php b/mod/quiz/report/overview/lang/en/quiz_overview.php index dc188c22a7288..60d89679a8ebd 100644 --- a/mod/quiz/report/overview/lang/en/quiz_overview.php +++ b/mod/quiz/report/overview/lang/en/quiz_overview.php @@ -53,6 +53,9 @@ $string['preferencespage'] = 'Preferences just for this page'; $string['preferencessave'] = 'Show report'; $string['preferencesuser'] = 'Your preferences for this report'; +$string['privacy:metadata:preference:quiz_overview_slotmarks'] = 'Whether to show marks for each question slot.'; +$string['privacy:preference:slotmarks:yes'] = 'Marks are shown alongside the question slot.'; +$string['privacy:preference:slotmarks:no'] = 'Marks are not shown alongside the question slot.'; $string['regrade'] = 'Regrade'; $string['regradeall'] = 'Regrade all'; $string['regradealldry'] = 'Dry run a full regrade'; diff --git a/mod/quiz/report/overview/tests/privacy_provider_test.php b/mod/quiz/report/overview/tests/privacy_provider_test.php new file mode 100644 index 0000000000000..de59fcaa31f78 --- /dev/null +++ b/mod/quiz/report/overview/tests/privacy_provider_test.php @@ -0,0 +1,99 @@ +. + +/** + * Privacy provider tests. + * + * @package quiz_overview + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +use core_privacy\local\metadata\collection; +use quiz_overview\privacy\provider; +use core_privacy\local\request\writer; +use core_privacy\local\request\transform; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Privacy provider tests class. + * + * @package quiz_overview + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class quiz_overview_privacy_provider_testcase extends \core_privacy\tests\provider_testcase { + /** + * When no preference exists, there should be no export. + */ + public function test_preference_unset() { + global $USER; + + $this->resetAfterTest(); + $this->setAdminUser(); + + provider::export_user_preferences($USER->id); + + $this->assertFalse(writer::with_context(\context_system::instance())->has_any_data()); + } + + /** + * Preference does exist. + */ + public function test_preference_yes() { + global $USER; + + $this->resetAfterTest(); + $this->setAdminUser(); + + set_user_preference('quiz_overview_slotmarks', 1); + + provider::export_user_preferences($USER->id); + + $writer = writer::with_context(\context_system::instance()); + $this->assertTrue($writer->has_any_data()); + + $preferences = $writer->get_user_preferences('quiz_overview'); + $this->assertNotEmpty($preferences->slotmarks); + $this->assertEquals(transform::yesno(1), $preferences->slotmarks->value); + $description = get_string('privacy:preference:slotmarks:yes', 'quiz_overview'); + $this->assertEquals($description, $preferences->slotmarks->description); + } + + /** + * Preference does exist and is no. + */ + public function test_preference_no() { + global $USER; + + $this->resetAfterTest(); + $this->setAdminUser(); + + set_user_preference('quiz_overview_slotmarks', 0); + + provider::export_user_preferences($USER->id); + + $writer = writer::with_context(\context_system::instance()); + $this->assertTrue($writer->has_any_data()); + + $preferences = $writer->get_user_preferences('quiz_overview'); + $this->assertNotEmpty($preferences->slotmarks); + $this->assertEquals(transform::yesno(0), $preferences->slotmarks->value); + $description = get_string('privacy:preference:slotmarks:no', 'quiz_overview'); + $this->assertEquals($description, $preferences->slotmarks->description); + } +} diff --git a/mod/quiz/report/responses/classes/privacy/provider.php b/mod/quiz/report/responses/classes/privacy/provider.php new file mode 100644 index 0000000000000..95e213b6da0bc --- /dev/null +++ b/mod/quiz/report/responses/classes/privacy/provider.php @@ -0,0 +1,99 @@ +. + +/** + * Privacy Subsystem implementation for quiz_responses. + * + * @package quiz_responses + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace quiz_responses\privacy; + +use core_privacy\local\metadata\collection; +use core_privacy\local\request\writer; +use core_privacy\local\request\transform; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/question/engine/questionattempt.php'); + +/** + * Privacy Subsystem for quiz_responses with user preferences. + * + * @copyright 2018 Andrew Nicols + * @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('quiz_report_responses_qtext', 'privacy:preference:qtext'); + $collection->add_user_preference('quiz_report_responses_resp', 'privacy:preference:resp'); + $collection->add_user_preference('quiz_report_responses_right', 'privacy:preference:right'); + $collection->add_user_preference('quiz_report_responses_which_tries', 'privacy:preference:which_tries'); + + 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) { + $preferences = [ + 'qtext', + 'resp', + 'right', + ]; + + foreach ($preferences as $key) { + $preference = get_user_preferences("quiz_report_responses_{$key}", null, $userid); + if (null !== $preference) { + $desc = get_string("privacy:preference:{$key}", 'quiz_responses'); + writer::export_user_preference('quiz_responses', $key, transform::yesno($preference), $desc); + } + } + + $preference = get_user_preferences("quiz_report_responses_which_tries", null, $userid); + if (null !== $preference) { + switch($preference) { + case \question_attempt::FIRST_TRY: + $value = get_string("privacy:preference:which_tries:first", 'quiz_responses'); + break; + case \question_attempt::LAST_TRY: + $value = get_string("privacy:preference:which_tries:last", 'quiz_responses'); + break; + case \question_attempt::ALL_TRIES: + $value = get_string("privacy:preference:which_tries:all", 'quiz_responses'); + break; + } + $desc = get_string("privacy:preference:which_tries", 'quiz_responses'); + + writer::export_user_preference('quiz_responses', 'which_tries', $value, $desc); + } + } +} diff --git a/mod/quiz/report/responses/lang/en/quiz_responses.php b/mod/quiz/report/responses/lang/en/quiz_responses.php index 7afc8a6973ac7..7bc319b993ec2 100644 --- a/mod/quiz/report/responses/lang/en/quiz_responses.php +++ b/mod/quiz/report/responses/lang/en/quiz_responses.php @@ -27,6 +27,13 @@ $string['mustselectcols'] = 'You must include something.'; $string['pagesize'] = 'Page size'; $string['pluginname'] = 'Responses'; +$string['privacy:preference:qtext'] = 'Whether to show the question text columns.'; +$string['privacy:preference:resp'] = 'Whether to show the students\' response columns.'; +$string['privacy:preference:right'] = 'Whether to show the correct response columns.'; +$string['privacy:preference:which_tries'] = 'Which tries to show responses from.'; +$string['privacy:preference:which_tries:first'] = 'The first try at a question during an attempt by a user.'; +$string['privacy:preference:which_tries:last'] = 'The last try at a question during an attempt by a user.'; +$string['privacy:preference:which_tries:all'] = 'All tries at a question during an attempt by a user.'; $string['questiontext'] = 'question text'; $string['reportresponses'] = 'Responses'; $string['response'] = 'response'; diff --git a/mod/quiz/report/responses/tests/privacy_provider_test.php b/mod/quiz/report/responses/tests/privacy_provider_test.php new file mode 100644 index 0000000000000..d39aa5b36d0fb --- /dev/null +++ b/mod/quiz/report/responses/tests/privacy_provider_test.php @@ -0,0 +1,139 @@ +. + +/** + * Privacy provider tests. + * + * @package quiz_responses + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +use core_privacy\local\metadata\collection; +use quiz_responses\privacy\provider; +use core_privacy\local\request\writer; +use core_privacy\local\request\transform; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/question/engine/questionattempt.php'); + +/** + * Privacy provider tests class. + * + * @package quiz_responses + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class quiz_responses_privacy_provider_testcase extends \core_privacy\tests\provider_testcase { + /** + * When no preference exists, there should be no export. + */ + public function test_preference_unset() { + global $USER; + + $this->resetAfterTest(); + $this->setAdminUser(); + + provider::export_user_preferences($USER->id); + + $this->assertFalse(writer::with_context(\context_system::instance())->has_any_data()); + } + + /** + * Preference does exist. + */ + public function test_preference_bool_true() { + global $USER; + + $this->resetAfterTest(); + $this->setAdminUser(); + + set_user_preference('quiz_report_responses_qtext', true); + set_user_preference('quiz_report_responses_resp', true); + set_user_preference('quiz_report_responses_right', true); + + provider::export_user_preferences($USER->id); + + $writer = writer::with_context(\context_system::instance()); + $this->assertTrue($writer->has_any_data()); + + $preferences = $writer->get_user_preferences('quiz_responses'); + + $this->assertNotEmpty($preferences->qtext); + $this->assertEquals(transform::yesno(1), $preferences->qtext->value); + + $this->assertNotEmpty($preferences->resp); + $this->assertEquals(transform::yesno(1), $preferences->resp->value); + + $this->assertNotEmpty($preferences->right); + $this->assertEquals(transform::yesno(1), $preferences->right->value); + } + + /** + * Preference does exist. + */ + public function test_preference_bool_false() { + global $USER; + + $this->resetAfterTest(); + $this->setAdminUser(); + + set_user_preference('quiz_report_responses_qtext', false); + set_user_preference('quiz_report_responses_resp', false); + set_user_preference('quiz_report_responses_right', false); + + provider::export_user_preferences($USER->id); + + $writer = writer::with_context(\context_system::instance()); + $this->assertTrue($writer->has_any_data()); + + $preferences = $writer->get_user_preferences('quiz_responses'); + + $this->assertNotEmpty($preferences->qtext); + $this->assertEquals(transform::yesno(0), $preferences->qtext->value); + + $this->assertNotEmpty($preferences->resp); + $this->assertEquals(transform::yesno(0), $preferences->resp->value); + + $this->assertNotEmpty($preferences->right); + $this->assertEquals(transform::yesno(0), $preferences->right->value); + } + + /** + * Preference does exist. + */ + public function test_preference_bool_which_first() { + global $USER; + + $this->resetAfterTest(); + $this->setAdminUser(); + + set_user_preference('quiz_report_responses_which_tries', question_attempt::FIRST_TRY); + + provider::export_user_preferences($USER->id); + + $writer = writer::with_context(\context_system::instance()); + $this->assertTrue($writer->has_any_data()); + + $preferences = $writer->get_user_preferences('quiz_responses'); + + $expected = get_string("privacy:preference:which_tries:first", 'quiz_responses'); + $this->assertNotEmpty($preferences->which_tries); + $this->assertEquals($expected, $preferences->which_tries->value); + } +} diff --git a/mod/quiz/report/statistics/classes/privacy/provider.php b/mod/quiz/report/statistics/classes/privacy/provider.php new file mode 100644 index 0000000000000..07cbcc15ec462 --- /dev/null +++ b/mod/quiz/report/statistics/classes/privacy/provider.php @@ -0,0 +1,46 @@ +. + +/** + * Privacy Subsystem implementation for quiz_statistics. + * + * @package quiz_statistics + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace quiz_statistics\privacy; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Privacy Subsystem for quiz_statistics implementing null_provider. + * + * @copyright 2018 Andrew Nicols + * @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'; + } +} diff --git a/mod/quiz/report/statistics/lang/en/quiz_statistics.php b/mod/quiz/report/statistics/lang/en/quiz_statistics.php index 64f562cbadcf2..38895d02e1316 100644 --- a/mod/quiz/report/statistics/lang/en/quiz_statistics.php +++ b/mod/quiz/report/statistics/lang/en/quiz_statistics.php @@ -86,6 +86,7 @@ $string['optiongrade'] = 'Partial credit'; $string['partofquestion'] = 'Part of question'; $string['pluginname'] = 'Statistics'; +$string['privacy:metadata'] = 'Although the Quiz Statistics plugin has database tables, the data is aggregate data and does not describe a unique indidividual.'; $string['position'] = 'Position'; $string['positions'] = 'Position(s)'; $string['questioninformation'] = 'Question information'; @@ -115,4 +116,3 @@ $string['statsfor'] = 'Quiz statistics (for {$a})'; $string['variant'] = 'Variant'; $string['whichtries'] = 'Analyze responses for'; -