From f3a6d9bb7697b3a8e24075a5bd015cdf28565f98 Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Thu, 14 Jun 2018 10:38:19 +0800 Subject: [PATCH] MDL-62535 core_grading: Update to providers and interface. The previous interface was inadequate for retrieving user information stored in the sub-plugins. A new interface and methods have been added to successfully deal with user data. --- .../privacy/gradingform_legacy_polyfill.php | 34 +++++++- .../classes/privacy/gradingform_provider.php | 15 +++- .../privacy/gradingform_provider_v2.php | 46 ++++++++++ grade/grading/classes/privacy/provider.php | 87 +++++++++++++++++-- .../form/guide/classes/privacy/provider.php | 39 +++++++++ .../form/guide/lang/en/gradingform_guide.php | 5 ++ .../form/rubric/classes/privacy/provider.php | 54 ++++++++++-- .../rubric/lang/en/gradingform_rubric.php | 6 +- grade/grading/form/upgrade.txt | 5 ++ 9 files changed, 273 insertions(+), 18 deletions(-) create mode 100644 grade/grading/classes/privacy/gradingform_provider_v2.php diff --git a/grade/grading/classes/privacy/gradingform_legacy_polyfill.php b/grade/grading/classes/privacy/gradingform_legacy_polyfill.php index 86ef9d10536..799e8277192 100644 --- a/grade/grading/classes/privacy/gradingform_legacy_polyfill.php +++ b/grade/grading/classes/privacy/gradingform_legacy_polyfill.php @@ -26,8 +26,6 @@ namespace core_grading\privacy; defined('MOODLE_INTERNAL') || die(); -use core_privacy\local\request\approved_contextlist; - /** * The trait used to provide backwards compatability for third-party plugins. * @@ -36,9 +34,32 @@ use core_privacy\local\request\approved_contextlist; */ trait gradingform_legacy_polyfill { + /** + * Export user data relating to an instance ID. + * + * @param \context $context Context to use with the export writer. + * @param int $instanceid The instance ID to export data for. + * @param array $subcontext The directory to export this data to. + */ + public static function export_gradingform_instance_data(\context $context, int $instanceid, array $subcontext) { + static::_export_gradingform_instance_data($context, $instanceid, $subcontext); + } + + /** + * Deletes all user data related to the provided instance IDs. + * + * @param array $instanceids The instance IDs to delete information from. + */ + public static function delete_gradingform_for_instances(array $instanceids) { + static::_delete_gradingform_for_instances($instanceids); + } + /** * This method is used to export any user data this sub-plugin has using the object to get the context and userid. * + * @deprecated Since Moodle 3.6 MDL-62535 Please use the methods in the gradingform_provider_v2 interface. + * @todo MDL-63137 remove this method. + * * @param context $context Context owner of the data. * @param stdClass $definition Grading definition entry to export. * @param int $userid The user whose information is to be exported. @@ -46,25 +67,34 @@ trait gradingform_legacy_polyfill { * @return stdClass The data to export. */ public static function get_gradingform_export_data(\context $context, $definition, int $userid) { + debugging('This method is deprecated. Please use the gradingform_provider_v2 interface', DEBUG_DEVELOPER); return static::_get_gradingform_export_data($context, $definition, $userid); } /** * Any call to this method should delete all user data for the context defined. * + * @deprecated Since Moodle 3.6 MDL-62535 Please use the methods in the gradingform_provider_v2 interface. + * @todo MDL-63137 remove this method. + * * @param context $context Context owner of the data. */ public static function delete_gradingform_for_context(\context $context) { + debugging('This method is deprecated. Please use the gradingform_provider_v2 interface', DEBUG_DEVELOPER); static::_delete_gradingform_for_context($context); } /** * A call to this method should delete user data (where practicle) from the userid and context. * + * @deprecated Since Moodle 3.6 MDL-62535 Please use the methods in the gradingform_provider_v2 interface. + * @todo MDL-63137 remove this method. + * * @param int $userid The user whose information is to be deleted. * @param context $context Context owner of the data. */ public static function delete_gradingform_for_userid(int $userid, \context $context) { + debugging('This method is deprecated. Please use the gradingform_provider_v2 interface', DEBUG_DEVELOPER); static::_delete_gradingform_for_userid($userid, $context); } } diff --git a/grade/grading/classes/privacy/gradingform_provider.php b/grade/grading/classes/privacy/gradingform_provider.php index b8239f13841..16029569c30 100644 --- a/grade/grading/classes/privacy/gradingform_provider.php +++ b/grade/grading/classes/privacy/gradingform_provider.php @@ -19,6 +19,9 @@ * * Grading method plugins should implement this if they store personal information. * + * @deprecated since Moodle 3.6 MDL-62535 Please use the gradingform_provider_v2 interface + * @todo MDL-63167 Remove this file. + * * @package core_grading * @copyright 2018 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -31,11 +34,15 @@ defined('MOODLE_INTERNAL') || die(); use core_privacy\local\request\approved_contextlist; interface gradingform_provider extends - \core_privacy\local\request\plugin\subsystem_provider { + \core_privacy\local\request\plugin\subsystem_provider, + \core_privacy\local\deprecated { /** * This method is used to export any user data this sub-plugin has using the object to get the context and userid. * + * @deprecated since Moodle 3.6 MDL-62535 Please use the methods in the gradingform_provider_v2 interface + * @todo MDL-63167 Remove this file. + * * @param \context $context Context owner of the data. * @param \stdClass $definition Grading definition entry to export. * @param int $userid The user whose information is to be exported. @@ -47,6 +54,9 @@ interface gradingform_provider extends /** * Any call to this method should delete all user data for the context defined. * + * @deprecated since Moodle 3.6 MDL-62535 Please use the methods in the gradingform_provider_v2 interface + * @todo MDL-63167 Remove this file. + * * @param \context $context Context owner of the data. */ public static function delete_gradingform_for_context(\context $context); @@ -54,6 +64,9 @@ interface gradingform_provider extends /** * A call to this method should delete user data (where practicle) from the userid and context. * + * @deprecated since Moodle 3.6 MDL-62535 Please use the methods in the gradingform_provider_v2 interface + * @todo MDL-63167 Remove this file. + * * @param int $userid The user to delete. * @param \context $context the context to refine the deletion. */ diff --git a/grade/grading/classes/privacy/gradingform_provider_v2.php b/grade/grading/classes/privacy/gradingform_provider_v2.php new file mode 100644 index 00000000000..fa71f135782 --- /dev/null +++ b/grade/grading/classes/privacy/gradingform_provider_v2.php @@ -0,0 +1,46 @@ +. + +/** + * Privacy class for requesting user data. + * + * @package core_grading + * @copyright 2018 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace core_grading\privacy; + +defined('MOODLE_INTERNAL') || die(); + +interface gradingform_provider_v2 extends + \core_privacy\local\request\plugin\subsystem_provider { + + /** + * Export user data relating to an instance ID. + * + * @param \context $context Context to use with the export writer. + * @param int $instanceid The instance ID to export data for. + * @param array $subcontext The directory to export this data to. + */ + public static function export_gradingform_instance_data(\context $context, int $instanceid, array $subcontext); + + /** + * Deletes all user data related to the provided instance IDs. + * + * @param array $instanceids The instance IDs to delete information from. + */ + public static function delete_gradingform_for_instances(array $instanceids); +} diff --git a/grade/grading/classes/privacy/provider.php b/grade/grading/classes/privacy/provider.php index 490cc791dd2..24ce67af9d6 100644 --- a/grade/grading/classes/privacy/provider.php +++ b/grade/grading/classes/privacy/provider.php @@ -133,6 +133,73 @@ class provider implements } } + /** + * Export all user data related to a context and itemid. + * + * @param \context $context Context to export on. + * @param int $itemid Item ID to export on. + * @param array $subcontext Directory location to export to. + */ + public static function export_item_data(\context $context, int $itemid, array $subcontext) { + global $DB; + + $sql = "SELECT gi.id AS instanceid, gd.id AS definitionid, gd.method + FROM {grading_areas} ga + JOIN {grading_definitions} gd ON gd.areaid = ga.id + JOIN {grading_instances} gi ON gi.definitionid = gd.id AND gi.itemid = :itemid + WHERE ga.contextid = :contextid"; + $params = [ + 'itemid' => $itemid, + 'contextid' => $context->id, + ]; + $records = $DB->get_recordset_sql($sql, $params); + foreach ($records as $record) { + $instancedata = manager::component_class_callback( + "gradingform_{$record->method}", + gradingform_provider_v2::class, + 'export_gradingform_instance_data', + [$context, $record->instanceid, $subcontext] + ); + } + $records->close(); + } + + /** + * Deletes all user data related to a context and possibly an itemid. + * + * @param \context $context The context to delete on. + * @param int|null $itemid An optional item ID to refine the deletion. + */ + public static function delete_instance_data(\context $context, int $itemid = null) { + global $DB; + $itemsql = ''; + $params = ['contextid' => $context->id]; + if (isset($itemid)) { + $params['itemid'] = $itemid; + $itemsql = 'AND gi.itemid = :itemid'; + } + $sql = "SELECT gi.id AS instanceid, gd.id, gd.method + FROM {grading_definitions} gd + JOIN {grading_instances} gi ON gi.definitionid = gd.id + JOIN {grading_areas} ga ON ga.id = gd.areaid + WHERE ga.contextid = :contextid $itemsql"; + $records = $DB->get_records_sql($sql, $params); + if ($records) { + $firstrecord = current($records); + $method = $firstrecord->method; + $instanceids = array_map(function($record) { + return $record->instanceid; + }, $records); + manager::component_class_callback( + "gradingform_{$method}", + gradingform_provider_v2::class, + 'delete_gradingform_for_instances', + [$instanceids]); + // Delete grading_instances rows. + $DB->delete_records_list('grading_instances', 'id', $instanceids); + } + } + /** * Exports the data related to grading definitions within the specified context/subcontext. * @@ -191,6 +258,8 @@ class provider implements if (!empty($definition->timecopied)) { $tmpdata['timecopied'] = transform::datetime($definition->timecopied); } + + // MDL-63167 - This section is to be removed with the final deprecation of the gradingform_provider interface. // Export gradingform information (if needed). $instancedata = manager::component_class_callback( "gradingform_{$definition->method}", @@ -201,6 +270,7 @@ class provider implements if (null !== $instancedata) { $tmpdata = array_merge($tmpdata, $instancedata); } + // End of section to be removed with deprecation. $defdata[] = (object) $tmpdata; @@ -258,34 +328,35 @@ class provider implements } /** - * Delete all use data which matches the specified $context. + * No deletion of the advanced grading is done. * - * We never delete grading content. - * - * @param context $context A user context. + * @param \context $context the context to delete in. */ public static function delete_data_for_all_users_in_context(\context $context) { + // MDL-63167 - This section is to be removed with the final deprecation of the gradingform_provider interface. manager::plugintype_class_callback( 'gradingform', gradingform_provider::class, 'delete_gradingform_for_context', [$context] ); + // End of section to be removed for final deprecation. } /** - * Delete all user data for the specified user, in the specified contexts. + * Deletion of data in this provider is only related to grades and so can not be + * deleted for the creator of the advanced grade criteria. * - * We never delete grading content. - * - * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. + * @param approved_contextlist $contextlist a list of contexts approved for deletion. */ public static function delete_data_for_user(approved_contextlist $contextlist) { + // MDL-63167 - This section is to be removed with the final deprecation of the gradingform_provider interface. manager::plugintype_class_callback( 'gradingform', gradingform_provider::class, 'delete_gradingform_for_userid', [$contextlist] ); + // End of section to be removed for final deprecation. } } diff --git a/grade/grading/form/guide/classes/privacy/provider.php b/grade/grading/form/guide/classes/privacy/provider.php index d5ec198df21..e22883fd138 100644 --- a/grade/grading/form/guide/classes/privacy/provider.php +++ b/grade/grading/form/guide/classes/privacy/provider.php @@ -38,6 +38,7 @@ use \core_privacy\local\request\writer; */ class provider implements \core_privacy\local\metadata\provider, + \core_grading\privacy\gradingform_provider_v2, \core_privacy\local\request\user_preference_provider { /** @@ -47,6 +48,12 @@ class provider implements * @return collection A listing of user data stored through this system. */ public static function get_metadata(collection $collection) : collection { + $collection->add_database_table('gradingform_guide_fillings', [ + 'instanceid' => 'privacy:metadata:instanceid', + 'criterionid' => 'privacy:metadata:criterionid', + 'remark' => 'privacy:metadata:remark', + 'score' => 'privacy:metadata:score' + ], 'privacy:metadata:fillingssummary'); $collection->add_user_preference( 'gradingform_guide-showmarkerdesc', 'privacy:metadata:preference:showmarkerdesc' @@ -59,6 +66,38 @@ class provider implements return $collection; } + /** + * Export user data relating to an instance ID. + * + * @param \context $context Context to use with the export writer. + * @param int $instanceid The instance ID to export data for. + * @param array $subcontext The directory to export this data to. + */ + public static function export_gradingform_instance_data(\context $context, int $instanceid, array $subcontext) { + global $DB; + // Get records from the provided params. + $params = ['instanceid' => $instanceid]; + $sql = "SELECT gc.shortname, gc.description, gc.maxscore, gf.score, gf.remark + FROM {gradingform_guide_fillings} gf + JOIN {gradingform_guide_criteria} gc ON gc.id = gf.criterionid + WHERE gf.instanceid = :instanceid"; + $records = $DB->get_records_sql($sql, $params); + if ($records) { + $subcontext = array_merge($subcontext, [get_string('guide', 'gradingform_guide')]); + writer::with_context($context)->export_data($subcontext, (object) $records); + } + } + + /** + * Deletes all user data related to the provided instance IDs. + * + * @param array $instanceids The instance IDs to delete information from. + */ + public static function delete_gradingform_for_instances(array $instanceids) { + global $DB; + $DB->delete_records_list('gradingform_guide_fillings', 'instanceid', $instanceids); + } + /** * Store all user preferences for the plugin. * diff --git a/grade/grading/form/guide/lang/en/gradingform_guide.php b/grade/grading/form/guide/lang/en/gradingform_guide.php index 3073ae5db2b..7499a4c41a3 100644 --- a/grade/grading/form/guide/lang/en/gradingform_guide.php +++ b/grade/grading/form/guide/lang/en/gradingform_guide.php @@ -75,8 +75,13 @@ $string['name'] = 'Name'; $string['needregrademessage'] = 'The marking guide definition was changed after this student had been graded. The student can not see this marking guide until you check the marking guide and update the grade.'; $string['pluginname'] = 'Marking guide'; $string['previewmarkingguide'] = 'Preview marking guide'; +$string['privacy:metadata:criterionid'] = 'An identifier to a criterion for advanced marking.'; +$string['privacy:metadata:fillingssummary'] = 'Stores information about a user\'s grade and feedback for the marking guide.'; +$string['privacy:metadata:instanceid'] = 'An identifier to a grade used by an activity.'; $string['privacy:metadata:preference:showmarkerdesc'] = 'Whether to show marker criterion descriptions'; $string['privacy:metadata:preference:showstudentdesc'] = 'Whether to show student criterion descriptions'; +$string['privacy:metadata:remark'] = 'Remarks related to this grade criterion.'; +$string['privacy:metadata:score'] = 'A score for this grade criterion.'; $string['regrademessage1'] = 'You are about to save changes to a marking guide that has already been used for grading. Please indicate if existing grades need to be reviewed. If you set this then the marking guide will be hidden from students until their item is regraded.'; $string['regrademessage5'] = 'You are about to save significant changes to a marking guide that has already been used for grading. The gradebook value will be unchanged, but the marking guide will be hidden from students until their item is regraded.'; $string['regradeoption0'] = 'Do not mark for regrade'; diff --git a/grade/grading/form/rubric/classes/privacy/provider.php b/grade/grading/form/rubric/classes/privacy/provider.php index 53bd41bd5a7..e3304fc022f 100644 --- a/grade/grading/form/rubric/classes/privacy/provider.php +++ b/grade/grading/form/rubric/classes/privacy/provider.php @@ -26,6 +26,8 @@ namespace gradingform_rubric\privacy; defined('MOODLE_INTERNAL') || die(); +use \core_privacy\local\metadata\collection; + /** * Privacy class for requesting user data. * @@ -33,15 +35,55 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements - \core_privacy\local\metadata\null_provider { + \core_privacy\local\metadata\provider, + \core_grading\privacy\gradingform_provider_v2 { /** - * Get the language string identifier with the component's language - * file to explain why this plugin stores no data. + * Returns meta data about this system. * - * @return string + * @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_reason() : string { - return 'privacy:metadata'; + public static function get_metadata(collection $collection) : collection { + $collection->add_database_table('gradingform_rubric_fillings', [ + 'instanceid' => 'privacy:metadata:instanceid', + 'criterionid' => 'privacy:metadata:criterionid', + 'levelid' => 'privacy:metadata:levelid', + 'remark' => 'privacy:metadata:remark' + ], 'privacy:metadata:fillingssummary'); + return $collection; + } + + /** + * Export user data relating to an instance ID. + * + * @param \context $context Context to use with the export writer. + * @param int $instanceid The instance ID to export data for. + * @param array $subcontext The directory to export this data to. + */ + public static function export_gradingform_instance_data(\context $context, int $instanceid, array $subcontext) { + global $DB; + // Get records from the provided params. + $params = ['instanceid' => $instanceid]; + $sql = "SELECT rc.description, rl.definition, rl.score, rf.remark + FROM {gradingform_rubric_fillings} rf + JOIN {gradingform_rubric_criteria} rc ON rc.id = rf.criterionid + JOIN {gradingform_rubric_levels} rl ON rf.levelid = rl.id + WHERE rf.instanceid = :instanceid"; + $records = $DB->get_records_sql($sql, $params); + if ($records) { + $subcontext = array_merge($subcontext, [get_string('rubric', 'gradingform_rubric')]); + \core_privacy\local\request\writer::with_context($context)->export_data($subcontext, (object) $records); + } + } + + /** + * Deletes all user data related to the provided instance IDs. + * + * @param array $instanceids The instance IDs to delete information from. + */ + public static function delete_gradingform_for_instances(array $instanceids) { + global $DB; + $DB->delete_records_list('gradingform_rubric_fillings', 'instanceid', $instanceids); } } diff --git a/grade/grading/form/rubric/lang/en/gradingform_rubric.php b/grade/grading/form/rubric/lang/en/gradingform_rubric.php index be7e1801eab..d5951aec2f5 100644 --- a/grade/grading/form/rubric/lang/en/gradingform_rubric.php +++ b/grade/grading/form/rubric/lang/en/gradingform_rubric.php @@ -59,7 +59,11 @@ $string['name'] = 'Name'; $string['needregrademessage'] = 'The rubric definition was changed after this student had been graded. The student can not see this rubric until you check the rubric and update the grade.'; $string['pluginname'] = 'Rubric'; $string['previewrubric'] = 'Preview rubric'; -$string['privacy:metadata'] = 'The rubric grading form plugin does not store any personal data.'; +$string['privacy:metadata:criterionid'] = 'An identifier for a specific criterion being graded.'; +$string['privacy:metadata:fillingssummary'] = 'Stores information about the user\'s grade created by the rubric.'; +$string['privacy:metadata:instanceid'] = 'An identifier relating to a grade in an activity.'; +$string['privacy:metadata:levelid'] = 'The level obtained in the rubric.'; +$string['privacy:metadata:remark'] = 'Remarks related to the rubric criterion being assessed.'; $string['regrademessage1'] = 'You are about to save changes to a rubric that has already been used for grading. Please indicate if existing grades need to be reviewed. If you set this then the rubric will be hidden from students until their item is regraded.'; $string['regrademessage5'] = 'You are about to save significant changes to a rubric that has already been used for grading. The gradebook value will be unchanged, but the rubric will be hidden from students until their item is regraded.'; $string['regradeoption0'] = 'Do not mark for regrade'; diff --git a/grade/grading/form/upgrade.txt b/grade/grading/form/upgrade.txt index 21cc6316240..0bca3144f0a 100644 --- a/grade/grading/form/upgrade.txt +++ b/grade/grading/form/upgrade.txt @@ -1,6 +1,11 @@ This files describes API changes in /grade/grading/form/* - Advanced grading methods information provided here is intended especially for developers. +=== 3.6 === + +* The privacy interface gradingform_provider has been deprecated. Please use + gradingform_provider_v2 instead. + === 2.5.2 === * Grading methods now can return grade with decimals. See API functions