MDL-62535 core_grading: Update to providers and interface.
authorAdrian Greeve <adrian@moodle.com>
Thu, 14 Jun 2018 02:38:19 +0000 (10:38 +0800)
committerAdrian Greeve <abgreeve@gmail.com>
Mon, 20 Aug 2018 03:32:01 +0000 (11:32 +0800)
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.

grade/grading/classes/privacy/gradingform_legacy_polyfill.php
grade/grading/classes/privacy/gradingform_provider.php
grade/grading/classes/privacy/gradingform_provider_v2.php [new file with mode: 0644]
grade/grading/classes/privacy/provider.php
grade/grading/form/guide/classes/privacy/provider.php
grade/grading/form/guide/lang/en/gradingform_guide.php
grade/grading/form/rubric/classes/privacy/provider.php
grade/grading/form/rubric/lang/en/gradingform_rubric.php
grade/grading/form/upgrade.txt

index 86ef9d1..799e827 100644 (file)
@@ -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);
     }
 }
index b8239f1..1602956 100644 (file)
@@ -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 <sara@moodle.com>
  * @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 (file)
index 0000000..fa71f13
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Privacy class for requesting user data.
+ *
+ * @package    core_grading
+ * @copyright  2018 Adrian Greeve <adriangreeve.com>
+ * @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);
+}
index 490cc79..24ce67a 100644 (file)
@@ -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.
-     *
-     * We never delete grading content.
+     * 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.
      *
-     * @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.
     }
 }
index d5ec198..e22883f 100644 (file)
@@ -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.
      *
index 3073ae5..7499a4c 100644 (file)
@@ -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';
index 53bd41b..e3304fc 100644 (file)
@@ -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 {
+
+    /**
+     * 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_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);
+        }
+    }
 
     /**
-     * Get the language string identifier with the component's language
-     * file to explain why this plugin stores no data.
+     * Deletes all user data related to the provided instance IDs.
      *
-     * @return  string
+     * @param  array  $instanceids The instance IDs to delete information from.
      */
-    public static function get_reason() : string {
-        return 'privacy:metadata';
+    public static function delete_gradingform_for_instances(array $instanceids) {
+        global $DB;
+        $DB->delete_records_list('gradingform_rubric_fillings', 'instanceid', $instanceids);
     }
 }
index be7e180..d5951ae 100644 (file)
@@ -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';
index 21cc631..0bca314 100644 (file)
@@ -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