MDL-62433 tool_policy: Adjustments to the data export
authorAndrew Nicols <andrew@nicols.co.uk>
Tue, 15 May 2018 02:57:28 +0000 (10:57 +0800)
committerSara Arjona <sara@moodle.com>
Tue, 15 May 2018 12:07:31 +0000 (14:07 +0200)
admin/tool/policy/classes/privacy/provider.php
admin/tool/policy/lang/en/tool_policy.php
admin/tool/policy/tests/privacy_provider_test.php

index 772819d..e01168f 100644 (file)
@@ -102,17 +102,30 @@ class provider implements
     public static function get_contexts_for_userid(int $userid) : contextlist {
         $contextlist = new contextlist();
 
+        // Policies a user has modified.
         $sql = "SELECT c.id
                   FROM {context} c
-             LEFT JOIN {tool_policy_versions} v ON v.usermodified = c.instanceid
-             LEFT JOIN {tool_policy_acceptances} a ON a.userid = c.instanceid
-                 WHERE c.contextlevel = :contextlevel
-                   AND (v.usermodified = :usermodified OR a.userid = :userid OR a.usermodified = :behalfuserid)";
+                  JOIN {tool_policy_versions} v ON v.usermodified = :userid
+                 WHERE c.contextlevel = :contextlevel";
+        $params = [
+            'contextlevel' => CONTEXT_SYSTEM,
+            'userid' => $userid,
+        ];
+        $contextlist->add_from_sql($sql, $params);
+
+        // Policies a user has accepted.
+        $sql = "SELECT c.id
+                  FROM {context} c
+                  JOIN {tool_policy_acceptances} a ON c.instanceid = a.userid
+                 WHERE
+                    c.contextlevel = :contextlevel
+                   AND (
+                    a.userid = :userid OR a.usermodified = :usermodified
+                   )";
         $params = [
             'contextlevel' => CONTEXT_USER,
+            'userid' => $userid,
             'usermodified' => $userid,
-            'userid'       => $userid,
-            'behalfuserid' => $userid,
         ];
         $contextlist->add_from_sql($sql, $params);
 
@@ -132,6 +145,9 @@ class provider implements
             if ($context->contextlevel == CONTEXT_USER) {
                 $carry[$context->instanceid] = $context;
             }
+            if ($context->contextlevel == CONTEXT_SYSTEM) {
+                $carry[$context->instanceid] = $context;
+            }
             return $carry;
         }, []);
 
@@ -145,43 +161,124 @@ class provider implements
             get_string('useracceptances', 'tool_policy')
         ];
         $policyversionids = [];
+
+        $agreementsql = "SELECT
+                            a.id, a.userid, v.name, v.revision, a.usermodified, a.timecreated,
+                            a.timemodified, a.note, v.archived, p.currentversionid, a.status, a.policyversionid
+                         FROM {tool_policy_acceptances} a
+                         JOIN {tool_policy_versions} v ON v.id = a.policyversionid
+                         JOIN {tool_policy} p ON v.policyid = p.id
+                        WHERE a.userid = :userid OR a.usermodified = :usermodified";
         foreach ($contexts as $context) {
-            $user = $contextlist->get_user();
-            $agreements = $DB->get_records_sql('SELECT a.id, a.userid, v.name, v.revision, a.usermodified, a.timecreated,
-                  a.timemodified, a.note, v.archived, p.currentversionid, a.status, a.policyversionid
-                FROM {tool_policy_acceptances} a
-                JOIN {tool_policy_versions} v ON v.id = a.policyversionid
-                JOIN {tool_policy} p ON v.policyid = p.id
-                WHERE a.userid = ? AND (a.userid = ? OR a.usermodified = ?)
-                ORDER BY a.userid, v.archived, v.timecreated DESC',
-                [$context->instanceid, $user->id, $user->id]);
-            foreach ($agreements as $agreement) {
-                $context = \context_user::instance($agreement->userid);
-                $name = 'policyagreement-' . $agreement->policyversionid;
-                $agreementcontent = (object) [
-                    'name' => $agreement->name,
-                    'revision' => $agreement->revision,
-                    'isactive' => transform::yesno($agreement->policyversionid == $agreement->currentversionid),
-                    'isagreed' => transform::yesno($agreement->status),
-                    'agreedby' => transform::user($agreement->usermodified),
-                    'timecreated' => transform::datetime($agreement->timecreated),
-                    'timemodified' => transform::datetime($agreement->timemodified),
-                    'note' => $agreement->note,
-                ];
-                writer::with_context($context)->export_related_data($subcontext, $name, $agreementcontent);
-                $policyversionids[$agreement->policyversionid] = $agreement->policyversionid;
+            if ($context->contextlevel == CONTEXT_USER) {
+                static::export_policy_agreements_for_context($context);
+            } else if ($context->contextlevel == CONTEXT_SYSTEM) {
+                static::export_authored_policies($contextlist->get_user());
             }
         }
+    }
+
+    /**
+     * Delete all data for all users in the specified context.
+     *
+     * We never delete user agreements to the policies because they are part of privacy data.
+     *
+     * @param \context $context The context to delete in.
+     */
+    public static function delete_data_for_all_users_in_context(\context $context) {
+    }
+
+    /**
+     * Delete all user data for the specified user, in the specified contexts.
+     *
+     * We never delete user agreements to the policies because they are part of privacy data.
+     *
+     * @param approved_contextlist $contextlist A list of contexts approved for deletion.
+     */
+    public static function delete_data_for_user(approved_contextlist $contextlist) {
+    }
+
+    /**
+     * Export all policy agreements relating to the specified user context.
+     *
+     * @param \context_user $context The context to export
+     */
+    protected static function export_policy_agreements_for_context(\context_user $context) {
+        global $DB;
+
+        $agreementsql = "
+            SELECT
+                a.id, a.userid, a.timemodified, a.note, a.status, a.policyversionid, a.usermodified, a.timecreated,
+                v.id AS versionid, v.archived, v.name, v.revision,
+                v.summary, v.summaryformat,
+                v.content, v.contentformat,
+                p.currentversionid
+             FROM {tool_policy_acceptances} a
+             JOIN {tool_policy_versions} v ON v.id = a.policyversionid
+             JOIN {tool_policy} p ON v.policyid = p.id
+            WHERE a.userid = :userid OR a.usermodified = :usermodified";
+
+        // Fetch all agreements related to this user.
+        $agreements = $DB->get_recordset_sql($agreementsql, [
+            'userid' => $context->instanceid,
+            'usermodified' => $context->instanceid,
+        ]);
+
+        $basecontext = [
+            get_string('privacyandpolicies', 'admin'),
+            get_string('useracceptances', 'tool_policy'),
+        ];
+
+        foreach ($agreements as $agreement) {
+            $subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $agreement)]);
+
+            $summary = writer::with_context($context)->rewrite_pluginfile_urls(
+                $subcontext,
+                'tool_policy',
+                'policydocumentsummary',
+                $agreement->versionid,
+                $agreement->summary
+            );
+            $content = writer::with_context($context)->rewrite_pluginfile_urls(
+                $subcontext,
+                'tool_policy',
+                'policydocumentcontent',
+                $agreement->versionid,
+                $agreement->content
+            );
+            $agreementcontent = (object) [
+                'name' => $agreement->name,
+                'revision' => $agreement->revision,
+                'isactive' => transform::yesno($agreement->policyversionid == $agreement->currentversionid),
+                'isagreed' => transform::yesno($agreement->status),
+                'agreedby' => transform::user($agreement->usermodified),
+                'timecreated' => transform::datetime($agreement->timecreated),
+                'timemodified' => transform::datetime($agreement->timemodified),
+                'note' => $agreement->note,
+                'summary' => format_text($summary, $agreement->summaryformat),
+                'content' => format_text($content, $agreement->contentformat),
+            ];
+
+            writer::with_context($context)
+                ->export_data($subcontext, $agreementcontent)
+                ->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $agreement->versionid)
+                ->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $agreement->versionid);
+        }
+        $agreements->close();
+    }
 
-        // Export policy versions (agreed or modified by the user).
-        $userid = $contextlist->get_user()->id;
+    /**
+     * Export all policy agreements that the user authored.
+     */
+    protected static function export_authored_policies(\stdClass $user) {
+        global $DB;
+
+        // Authored policies are exported against the system.
         $context = \context_system::instance();
-        $subcontext = [
-            get_string('policydocuments', 'tool_policy')
+        $basecontext = [
+            get_string('policydocuments', 'tool_policy'),
         ];
-        $writer = writer::with_context($context);
-        list($contextsql, $contextparams) = $DB->get_in_or_equal(array_keys($contexts), SQL_PARAMS_NAMED);
-        list($versionsql, $versionparams) = $DB->get_in_or_equal($policyversionids, SQL_PARAMS_NAMED);
+
         $sql = "SELECT v.id,
                        v.name,
                        v.revision,
@@ -194,22 +291,22 @@ class provider implements
                        p.currentversionid
                   FROM {tool_policy_versions} v
                   JOIN {tool_policy} p ON p.id = v.policyid
-                 WHERE v.usermodified {$contextsql} OR v.id {$versionsql}";
-        $params = array_merge($contextparams, $versionparams);
-        $versions = $DB->get_recordset_sql($sql, $params);
+                 WHERE v.usermodified = :userid";
+        $versions = $DB->get_recordset_sql($sql, ['userid' => $user->id]);
         foreach ($versions as $version) {
-            $name = 'policyversion-' . $version->id;
+            $subcontext = array_merge($basecontext, [get_string('policynamedversion', 'tool_policy', $version)]);
+
             $versioncontent = (object) [
                 'name' => $version->name,
                 'revision' => $version->revision,
-                'summary' => $writer->rewrite_pluginfile_urls(
+                'summary' => writer::with_context($context)->rewrite_pluginfile_urls(
                     $subcontext,
                     'tool_policy',
                     'policydocumentsummary',
                     $version->id,
                     $version->summary
                 ),
-                'content' => $writer->rewrite_pluginfile_urls(
+                'content' => writer::with_context($context)->rewrite_pluginfile_urls(
                     $subcontext,
                     'tool_policy',
                     'policydocumentcontent',
@@ -218,33 +315,15 @@ class provider implements
                 ),
                 'isactive' => transform::yesno($version->id == $version->currentversionid),
                 'isarchived' => transform::yesno($version->archived),
-                'createdbyme' => transform::yesno($version->usermodified == $userid),
+                'createdbyme' => transform::yesno($version->usermodified == $user->id),
                 'timecreated' => transform::datetime($version->timecreated),
                 'timemodified' => transform::datetime($version->timemodified),
             ];
-            $writer->export_related_data($subcontext, $name, $versioncontent);
-            $writer->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $version->id);
-            $writer->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $version->id);
+            writer::with_context($context)
+                ->export_data($subcontext, $versioncontent)
+                ->export_area_files($subcontext, 'tool_policy', 'policydocumentsummary', $version->id)
+                ->export_area_files($subcontext, 'tool_policy', 'policydocumentcontent', $version->id);
         }
-    }
-
-    /**
-     * Delete all data for all users in the specified context.
-     *
-     * We never delete user agreements to the policies because they are part of privacy data.
-     *
-     * @param \context $context The context to delete in.
-     */
-    public static function delete_data_for_all_users_in_context(\context $context) {
-    }
-
-    /**
-     * Delete all user data for the specified user, in the specified contexts.
-     *
-     * We never delete user agreements to the policies because they are part of privacy data.
-     *
-     * @param approved_contextlist $contextlist A list of contexts approved for deletion.
-     */
-    public static function delete_data_for_user(approved_contextlist $contextlist) {
+        $versions->close();
     }
 }
index ef5a5dc..5b06df4 100644 (file)
@@ -125,33 +125,34 @@ $string['policydoctype1'] = 'Privacy policy';
 $string['policydoctype2'] = 'Third parties policy';
 $string['policydoctype99'] = 'Other policy';
 $string['policydocuments'] = 'Policy documents';
+$string['policynamedversion'] = 'Policy {$a->name} (version {$a->revision})';
 $string['policyversionacceptedinbehalf'] = 'Consent for this policy has been given on your behalf.';
 $string['policyversionacceptedinotherlang'] = 'Consent for this policy version has been given in a different language.';
 $string['previousversions'] = '{$a} previous versions';
-$string['privacy:metadata:acceptances'] = 'Information from policy agreements made by site users';
-$string['privacy:metadata:acceptances:policyversionid'] = 'The ID of the accepted version policy.';
-$string['privacy:metadata:acceptances:userid'] = 'The ID of the user who agreed to the policy.';
-$string['privacy:metadata:acceptances:status'] = 'The status of the agreement: 0 if not accepted; 1 otherwise.';
-$string['privacy:metadata:acceptances:lang'] = 'The current language displayed when the policy is accepted.';
-$string['privacy:metadata:acceptances:usermodified'] = 'The ID of the user accepting the policy, if made on behalf of another user.';
+$string['privacy:metadata:acceptances'] = 'Information about policy agreements made by users';
+$string['privacy:metadata:acceptances:policyversionid'] = 'The version of the policy which was accepted.';
+$string['privacy:metadata:acceptances:userid'] = 'The user who this policy acceptances relates to.';
+$string['privacy:metadata:acceptances:status'] = 'The status of the agreement.';
+$string['privacy:metadata:acceptances:lang'] = 'The language used to display the policy when it was accepted.';
+$string['privacy:metadata:acceptances:usermodified'] = 'The user who accepted the policy, if made on behalf of another user.';
 $string['privacy:metadata:acceptances:timecreated'] = 'The time when the user agreed to the policy';
-$string['privacy:metadata:acceptances:timemodified'] = 'The time when the user modified their agreement';
+$string['privacy:metadata:acceptances:timemodified'] = 'The time when the user updated their agreement';
 $string['privacy:metadata:acceptances:note'] = 'Any comments added by a user when giving consent on behalf of another user';
-$string['privacy:metadata:subsystem:corefiles'] = 'Policy tool stores files embedded in to the policies summary or content text';
+$string['privacy:metadata:subsystem:corefiles'] = 'The policy tool stores files includes in the summary and content of a policy.';
 $string['privacy:metadata:versions'] = 'Information from versions of the policy documents';
-$string['privacy:metadata:versions:name'] = 'The policy document name.';
-$string['privacy:metadata:versions:type'] = 'The policy document type: site, privacy, third party...';
-$string['privacy:metadata:versions:audience'] = 'The policy document audience: all users, only authenticated users or only guests.';
+$string['privacy:metadata:versions:name'] = 'The name of the policy.';
+$string['privacy:metadata:versions:type'] = 'The type of policy document type.';
+$string['privacy:metadata:versions:audience'] = 'The intended audience of the policy.';
 $string['privacy:metadata:versions:archived'] = 'Whether the policy version is active or not.';
-$string['privacy:metadata:versions:usermodified'] = 'The ID of the user modifying the policy.';
-$string['privacy:metadata:versions:timecreated'] = 'The time when the policy version was created by the user.';
-$string['privacy:metadata:versions:timemodified'] = 'The time when the policy version was modified by the user.';
-$string['privacy:metadata:versions:policyid'] = 'The ID of the policy document where this version belongs.';
-$string['privacy:metadata:versions:revision'] = 'The policy version name.';
-$string['privacy:metadata:versions:summary'] = 'The policy version summary.';
-$string['privacy:metadata:versions:summaryformat'] = 'The policy version summary text format.';
-$string['privacy:metadata:versions:content'] = 'The policy version content.';
-$string['privacy:metadata:versions:contentformat'] = 'The policy version content text format.';
+$string['privacy:metadata:versions:usermodified'] = 'The user who modified the policy.';
+$string['privacy:metadata:versions:timecreated'] = 'The time that this version of the policy was created.';
+$string['privacy:metadata:versions:timemodified'] = 'The time that this version of the policy was updated.';
+$string['privacy:metadata:versions:policyid'] = 'The policy that this version is associated with.';
+$string['privacy:metadata:versions:revision'] = 'The revision name of this version of the policy.';
+$string['privacy:metadata:versions:summary'] = 'The summary of this version of the policy.';
+$string['privacy:metadata:versions:summaryformat'] = 'The format of the summary field.';
+$string['privacy:metadata:versions:content'] = 'The content of this version of the policy.';
+$string['privacy:metadata:versions:contentformat'] = 'The format of the content field.';
 $string['privacysettings'] = 'Privacy settings';
 $string['readpolicy'] = 'Please read our {$a}';
 $string['refertofullpolicytext'] = 'Please refer to the full {$a} if you would like to review the text.';
index 12ae6c1..438572b 100644 (file)
@@ -99,9 +99,12 @@ class tool_policy_privacy_provider_testcase extends \core_privacy\tests\provider
         $this->assertEquals(1, $contextlist->count());
     }
 
-    public function test_export_own_agreements() {
+    public function test_export_agreements() {
         global $CFG;
 
+        $otheruser = $this->getDataGenerator()->create_user();
+        $otherusercontext = \context_user::instance($otheruser->id);
+
         // Create policies and agree to them as manager.
         $this->setUser($this->manager);
         $managercontext = \context_user::instance($this->manager->id);
@@ -127,6 +130,7 @@ class tool_policy_privacy_provider_testcase extends \core_privacy\tests\provider
 
         // Request export for this user.
         $contextlist = provider::get_contexts_for_userid($this->user->id);
+        $this->assertCount(1, $contextlist);
         $this->assertEquals([$usercontext->id], $contextlist->get_contextids());
 
         $approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
@@ -134,34 +138,53 @@ class tool_policy_privacy_provider_testcase extends \core_privacy\tests\provider
 
         // User can not see manager's agreements but can see his own.
         $writer = writer::with_context($managercontext);
-        $datamanager = $writer->get_related_data($agreementsubcontext);
-        $this->assertEmpty($datamanager);
+        $this->assertFalse($writer->has_any_data());
 
         $writer = writer::with_context($usercontext);
-        $datauser = $writer->get_related_data($agreementsubcontext);
-        $this->assertCount(2, (array) $datauser);
-        $this->assertEquals($policy1->get('name'), $datauser['policyagreement-'.$policy1->get('id')]->name);
-        $this->assertEquals($this->user->id, $datauser['policyagreement-'.$policy1->get('id')]->agreedby);
-        $this->assertEquals($policy2->get('name'), $datauser['policyagreement-'.$policy2->get('id')]->name);
-        $this->assertEquals($this->user->id, $datauser['policyagreement-'.$policy2->get('id')]->agreedby);
-
+        $this->assertTrue($writer->has_any_data());
+
+        // Test policy 1.
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
+        $datauser = $writer->get_data($subcontext);
+        $this->assertEquals($policy1->get('name'), $datauser->name);
+        $this->assertEquals($this->user->id, $datauser->agreedby);
+        $this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
+        $this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
+
+        // Test policy 2.
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
+        $datauser = $writer->get_data($subcontext);
+        $this->assertEquals($policy2->get('name'), $datauser->name);
+        $this->assertEquals($this->user->id, $datauser->agreedby);
+        $this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
+        $this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
+
+        /**
         // User can see policy documents.
         $writer = writer::with_context($systemcontext);
-        $dataversion = $writer->get_related_data($versionsubcontext);
-        $this->assertCount(2, (array) $dataversion);
-        $this->assertEquals($policy1->get('name'), $dataversion['policyversion-'.$policy1->get('id')]->name);
-        $this->assertEquals(get_string('no'), $dataversion['policyversion-'.$policy1->get('id')]->createdbyme);
-        $this->assertEquals($policy2->get('name'), $dataversion['policyversion-'.$policy2->get('id')]->name);
-        $this->assertEquals(get_string('no'), $dataversion['policyversion-'.$policy2->get('id')]->createdbyme);
+        $this->assertTrue($writer->has_any_data());
+
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
+        $dataversion = $writer->get_data($subcontext);
+        $this->assertEquals($policy1->get('name'), $dataversion->name);
+        $this->assertEquals(get_string('no'), $dataversion->createdbyme);
+
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
+        $dataversion = $writer->get_data($subcontext);
+        $this->assertEquals($policy1->get('name'), $dataversion->name);
+        $this->assertEquals(get_string('no'), $dataversion->createdbyme);
+         */
     }
 
-    public function test_export_agreements_on_behalf() {
+    public function test_export_agreements_for_other() {
         global $CFG;
 
-        // Create policies.
-        $this->setUser($this->manager);
         $managercontext = \context_user::instance($this->manager->id);
         $systemcontext = \context_system::instance();
+        $usercontext = \context_user::instance($this->user->id);
+
+        // Create policies and agree to them as manager.
+        $this->setUser($this->manager);
         $agreementsubcontext = [
             get_string('privacyandpolicies', 'admin'),
             get_string('useracceptances', 'tool_policy')
@@ -174,79 +197,103 @@ class tool_policy_privacy_provider_testcase extends \core_privacy\tests\provider
         api::make_current($policy1->get('id'));
         $policy2 = $this->add_policy();
         api::make_current($policy2->get('id'));
-
-        // Agree to the policies for oneself and for another user.
-        $usercontext = \context_user::instance($this->user->id);
         api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
-        api::accept_policies([$policy1->get('id'), $policy2->get('id')], $this->user->id, 'Mynote');
 
-        // Request export for this user.
-        $contextlist = provider::get_contexts_for_userid($this->user->id);
-        $this->assertEquals([$usercontext->id], $contextlist->get_contextids());
+        // Agree to the other user's policies.
+        api::accept_policies([$policy1->get('id'), $policy2->get('id')], $this->user->id, 'My note');
 
-        $writer = writer::with_context($usercontext);
-        $this->assertFalse($writer->has_any_data());
+        // Request export for the manager.
+        $contextlist = provider::get_contexts_for_userid($this->manager->id);
+        $this->assertCount(3, $contextlist);
+        $this->assertEquals([$managercontext->id, $usercontext->id, $systemcontext->id], $contextlist->get_contextids(), '', 0.0, 1, true);
 
         $approvedcontextlist = new approved_contextlist($this->user, 'tool_policy', [$usercontext->id]);
         provider::export_user_data($approvedcontextlist);
 
-        // User can not see manager's agreements but can see his own.
-        $writer = writer::with_context($managercontext);
-        $datamanager = $writer->get_related_data($agreementsubcontext);
-        $this->assertEmpty($datamanager);
+        // The user context has data.
+        $writer = writer::with_context($usercontext);
+        $this->assertTrue($writer->has_any_data());
 
+        // Test policy 1.
         $writer = writer::with_context($usercontext);
-        $datauser = $writer->get_related_data($agreementsubcontext);
-        $this->assertCount(2, (array) $datauser);
-        $this->assertEquals($policy1->get('name'), $datauser['policyagreement-'.$policy1->get('id')]->name);
-        $this->assertEquals($this->manager->id, $datauser['policyagreement-'.$policy1->get('id')]->agreedby);
-        $this->assertEquals('Mynote', $datauser['policyagreement-'.$policy1->get('id')]->note);
-        $this->assertEquals($policy2->get('name'), $datauser['policyagreement-'.$policy2->get('id')]->name);
-        $this->assertEquals($this->manager->id, $datauser['policyagreement-'.$policy2->get('id')]->agreedby);
-        $this->assertEquals('Mynote', $datauser['policyagreement-'.$policy2->get('id')]->note);
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
+        $datauser = $writer->get_data($subcontext);
+        $this->assertEquals($policy1->get('name'), $datauser->name);
+        $this->assertEquals($this->manager->id, $datauser->agreedby);
+        $this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
+        $this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
+
+        // Test policy 2.
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
+        $datauser = $writer->get_data($subcontext);
+        $this->assertEquals($policy2->get('name'), $datauser->name);
+        $this->assertEquals($this->manager->id, $datauser->agreedby);
+        $this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
+        $this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
+    }
 
-        $writer = writer::with_context($systemcontext);
-        $dataversion = $writer->get_related_data($versionsubcontext);
-        $this->assertCount(2, (array) $dataversion);
-        $this->assertEquals($policy1->get('name'), $dataversion['policyversion-'.$policy1->get('id')]->name);
-        $this->assertEquals(get_string('no'), $dataversion['policyversion-'.$policy1->get('id')]->createdbyme);
-        $this->assertEquals($policy2->get('name'), $dataversion['policyversion-'.$policy2->get('id')]->name);
-        $this->assertEquals(get_string('no'), $dataversion['policyversion-'.$policy2->get('id')]->createdbyme);
+    public function test_export_created_policies() {
+        global $CFG;
 
-        // Request export for the manager.
-        writer::reset();
+        // Create policies and agree to them as manager.
+        $this->setUser($this->manager);
+        $managercontext = \context_user::instance($this->manager->id);
+        $systemcontext = \context_system::instance();
+        $agreementsubcontext = [
+            get_string('privacyandpolicies', 'admin'),
+            get_string('useracceptances', 'tool_policy')
+        ];
+        $versionsubcontext = [
+            get_string('policydocuments', 'tool_policy')
+        ];
+        $CFG->sitepolicyhandler = 'tool_policy';
+        $policy1 = $this->add_policy();
+        api::make_current($policy1->get('id'));
+        $policy2 = $this->add_policy();
+        api::make_current($policy2->get('id'));
+        api::accept_policies([$policy1->get('id'), $policy2->get('id')]);
+
+        // Agree to the policies for oneself.
         $contextlist = provider::get_contexts_for_userid($this->manager->id);
-        $this->assertEquals([$managercontext->id, $usercontext->id], $contextlist->get_contextids(), '', 0.0, 10, true);
+        $this->assertCount(2, $contextlist);
+        $this->assertEquals([$managercontext->id, $systemcontext->id], $contextlist->get_contextids(), '', 0.0, 1, true);
 
         $approvedcontextlist = new approved_contextlist($this->manager, 'tool_policy', $contextlist->get_contextids());
         provider::export_user_data($approvedcontextlist);
 
-        // Manager can see all four agreements.
+        // User has agreed to policies.
         $writer = writer::with_context($managercontext);
-        $datamanager = $writer->get_related_data($agreementsubcontext);
-        $this->assertCount(2, (array) $datamanager);
-        $this->assertEquals($policy1->get('name'), $datamanager['policyagreement-'.$policy1->get('id')]->name);
-        $this->assertEquals($this->manager->id, $datamanager['policyagreement-'.$policy1->get('id')]->agreedby);
-        $this->assertEquals($policy2->get('name'), $datamanager['policyagreement-'.$policy2->get('id')]->name);
-        $this->assertEquals($this->manager->id, $datamanager['policyagreement-'.$policy2->get('id')]->agreedby);
-
-        $writer = writer::with_context($usercontext);
-        $datauser = $writer->get_related_data($agreementsubcontext);
-        $this->assertCount(2, (array) $datauser);
-        $this->assertEquals($policy1->get('name'), $datauser['policyagreement-'.$policy1->get('id')]->name);
-        $this->assertEquals($this->manager->id, $datauser['policyagreement-'.$policy1->get('id')]->agreedby);
-        $this->assertEquals('Mynote', $datauser['policyagreement-'.$policy1->get('id')]->note);
-        $this->assertEquals($policy2->get('name'), $datauser['policyagreement-'.$policy2->get('id')]->name);
-        $this->assertEquals($this->manager->id, $datauser['policyagreement-'.$policy2->get('id')]->agreedby);
-        $this->assertEquals('Mynote', $datauser['policyagreement-'.$policy2->get('id')]->note);
+        $this->assertTrue($writer->has_any_data());
+
+        // Test policy 1.
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
+        $datauser = $writer->get_data($subcontext);
+        $this->assertEquals($policy1->get('name'), $datauser->name);
+        $this->assertEquals($this->manager->id, $datauser->agreedby);
+        $this->assertEquals(strip_tags($policy1->get('summary')), strip_tags($datauser->summary));
+        $this->assertEquals(strip_tags($policy1->get('content')), strip_tags($datauser->content));
+
+        // Test policy 2.
+        $subcontext = array_merge($agreementsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
+        $datauser = $writer->get_data($subcontext);
+        $this->assertEquals($policy2->get('name'), $datauser->name);
+        $this->assertEquals($this->manager->id, $datauser->agreedby);
+        $this->assertEquals(strip_tags($policy2->get('summary')), strip_tags($datauser->summary));
+        $this->assertEquals(strip_tags($policy2->get('content')), strip_tags($datauser->content));
 
+        // User can see policy documents.
         $writer = writer::with_context($systemcontext);
-        $dataversion = $writer->get_related_data($versionsubcontext);
-        $this->assertCount(2, (array) $dataversion);
-        $this->assertEquals($policy1->get('name'), $dataversion['policyversion-'.$policy1->get('id')]->name);
-        $this->assertEquals(get_string('yes'), $dataversion['policyversion-'.$policy1->get('id')]->createdbyme);
-        $this->assertEquals($policy2->get('name'), $dataversion['policyversion-'.$policy2->get('id')]->name);
-        $this->assertEquals(get_string('yes'), $dataversion['policyversion-'.$policy2->get('id')]->createdbyme);
+        $this->assertTrue($writer->has_any_data());
+
+        $subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy1->to_record())]);
+        $dataversion = $writer->get_data($subcontext);
+        $this->assertEquals($policy1->get('name'), $dataversion->name);
+        $this->assertEquals(get_string('yes'), $dataversion->createdbyme);
+
+        $subcontext = array_merge($versionsubcontext, [get_string('policynamedversion', 'tool_policy', $policy2->to_record())]);
+        $dataversion = $writer->get_data($subcontext);
+        $this->assertEquals($policy2->get('name'), $dataversion->name);
+        $this->assertEquals(get_string('yes'), $dataversion->createdbyme);
     }
 
     /**