Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Privacy Subsystem implementation for editor_atto.
19
 *
20
 * @package    editor_atto
21
 * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace editor_atto\privacy;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
use \core_privacy\local\request\approved_contextlist;
30
use \core_privacy\local\request\writer;
31
use \core_privacy\local\request\helper;
32
use \core_privacy\local\request\deletion_criteria;
33
use \core_privacy\local\metadata\collection;
34
use \core_privacy\local\request\userlist;
35
use \core_privacy\local\request\approved_userlist;
36
 
37
/**
38
 * Privacy Subsystem implementation for editor_atto.
39
 *
40
 * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
41
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42
 */
43
class provider implements
44
        // The Atto editor stores user provided data.
45
        \core_privacy\local\metadata\provider,
46
        // The Atto editor provides data directly to core.
47
        \core_privacy\local\request\plugin\provider,
48
        // The Atto editor is capable of determining which users have data within it.
49
        \core_privacy\local\request\core_userlist_provider {
50
 
51
    /**
52
     * Returns information about how editor_atto stores its data.
53
     *
54
     * @param   collection     $collection The initialised collection to add items to.
55
     * @return  collection     A listing of user data stored through this system.
56
     */
57
    public static function get_metadata(collection $collection): collection {
58
        // There isn't much point giving details about the pageid, etc.
59
        $collection->add_database_table('editor_atto_autosave', [
60
                'userid' => 'privacy:metadata:database:atto_autosave:userid',
61
                'drafttext' => 'privacy:metadata:database:atto_autosave:drafttext',
62
                'timemodified' => 'privacy:metadata:database:atto_autosave:timemodified',
63
            ], 'privacy:metadata:database:atto_autosave');
64
 
65
        return $collection;
66
    }
67
 
68
    /**
69
     * Get the list of contexts that contain user information for the specified user.
70
     *
71
     * @param   int         $userid     The user to search.
72
     * @return  contextlist   $contextlist  The contextlist containing the list of contexts used in this plugin.
73
     */
74
    public static function get_contexts_for_userid(int $userid): \core_privacy\local\request\contextlist {
75
        // This block doesn't know who information is stored against unless it
76
        // is at the user context.
77
        $contextlist = new \core_privacy\local\request\contextlist();
78
 
79
        $sql = "SELECT
80
                    c.id
81
                  FROM {editor_atto_autosave} eas
82
                  JOIN {context} c ON c.id = eas.contextid
83
                 WHERE contextlevel = :contextuser AND c.instanceid = :userid";
84
        $contextlist->add_from_sql($sql, ['contextuser' => CONTEXT_USER, 'userid' => $userid]);
85
 
86
        $sql = "SELECT contextid FROM {editor_atto_autosave} WHERE userid = :userid";
87
        $contextlist->add_from_sql($sql, ['userid' => $userid]);
88
 
89
        return $contextlist;
90
    }
91
 
92
    /**
93
     * Get the list of users within a specific context.
94
     *
95
     * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
96
     */
97
    public static function get_users_in_context(userlist $userlist) {
98
        $context = $userlist->get_context();
99
 
100
        $params = [
101
            'contextid' => $context->id
102
        ];
103
 
104
        $sql = "SELECT userid
105
                  FROM {editor_atto_autosave}
106
                 WHERE contextid = :contextid";
107
 
108
        $userlist->add_from_sql('userid', $sql, $params);
109
    }
110
 
111
    /**
112
     * Export all user data for the specified user, in the specified contexts.
113
     *
114
     * @param   approved_contextlist    $contextlist    The approved contexts to export information for.
115
     */
116
    public static function export_user_data(approved_contextlist $contextlist) {
117
        global $DB;
118
 
119
        $user = $contextlist->get_user();
120
 
121
        // Firstly export all autosave records from all contexts in the list owned by the given user.
122
 
123
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
124
        $contextparams['userid'] = $user->id;
125
 
126
        $sql = "SELECT *
127
                  FROM {editor_atto_autosave}
128
                 WHERE userid = :userid AND contextid {$contextsql}";
129
 
130
        $autosaves = $DB->get_recordset_sql($sql, $contextparams);
131
        self::export_autosaves($user, $autosaves);
132
 
133
        // Additionally export all eventual records in the given user's context regardless the actual owner.
134
        // We still consider them to be the user's personal data even when edited by someone else.
135
 
136
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
137
        $contextparams['userid'] = $user->id;
138
        $contextparams['contextuser'] = CONTEXT_USER;
139
 
140
        $sql = "SELECT eas.*
141
                  FROM {editor_atto_autosave} eas
142
                  JOIN {context} c ON c.id = eas.contextid
143
                 WHERE c.id {$contextsql} AND c.contextlevel = :contextuser AND c.instanceid = :userid";
144
 
145
        $autosaves = $DB->get_recordset_sql($sql, $contextparams);
146
        self::export_autosaves($user, $autosaves);
147
    }
148
 
149
    /**
150
     * Export all autosave records in the recordset, and close the recordset when finished.
151
     *
152
     * @param   \stdClass   $user The user whose data is to be exported
153
     * @param   \moodle_recordset $autosaves The recordset containing the data to export
154
     */
155
    protected static function export_autosaves(\stdClass $user, \moodle_recordset $autosaves) {
156
        foreach ($autosaves as $autosave) {
157
            $context = \context::instance_by_id($autosave->contextid);
158
            $subcontext = [
159
                get_string('autosaves', 'editor_atto'),
160
                $autosave->id,
161
            ];
162
 
163
            $html = writer::with_context($context)
164
                ->rewrite_pluginfile_urls($subcontext, 'user', 'draft', $autosave->draftid, $autosave->drafttext);
165
 
166
            $data = (object) [
167
                'drafttext' => format_text($html, FORMAT_HTML, static::get_filter_options()),
168
                'timemodified' => \core_privacy\local\request\transform::datetime($autosave->timemodified),
169
            ];
170
 
171
            if ($autosave->userid != $user->id) {
172
                $data->author = \core_privacy\local\request\transform::user($autosave->userid);
173
            }
174
 
175
            writer::with_context($context)
176
                ->export_data($subcontext, $data)
177
                ->export_area_files($subcontext, 'user', 'draft', $autosave->draftid);
178
        }
179
        $autosaves->close();
180
    }
181
 
182
    /**
183
     * Delete all data for all users in the specified context.
184
     *
185
     * @param   \context $context   The specific context to delete data for.
186
     */
187
    public static function delete_data_for_all_users_in_context(\context $context) {
188
        global $DB;
189
 
190
        $DB->delete_records('editor_atto_autosave', [
191
                'contextid' => $context->id,
192
            ]);
193
    }
194
 
195
    /**
196
     * Delete multiple users within a single context.
197
     *
198
     * @param approved_userlist $userlist The approved context and user information to delete information for.
199
     */
200
    public static function delete_data_for_users(approved_userlist $userlist) {
201
        global $DB;
202
 
203
        $context = $userlist->get_context();
204
        $userids = $userlist->get_userids();
205
 
206
        list($useridsql, $useridsqlparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
207
        $params = ['contextid' => $context->id] + $useridsqlparams;
208
 
209
        $DB->delete_records_select('editor_atto_autosave', "contextid = :contextid AND userid {$useridsql}",
210
            $params);
211
    }
212
 
213
    /**
214
     * Delete all user data for the specified user, in the specified contexts.
215
     *
216
     * @param   approved_contextlist    $contextlist    The approved contexts and user information to delete information for.
217
     */
218
    public static function delete_data_for_user(approved_contextlist $contextlist) {
219
        global $DB;
220
 
221
        $user = $contextlist->get_user();
222
 
223
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
224
        $contextparams['userid'] = $user->id;
225
 
226
        $sql = "SELECT * FROM {editor_atto_autosave} WHERE contextid {$contextsql}";
227
        $autosaves = $DB->delete_records_select('editor_atto_autosave', "userid = :userid AND contextid {$contextsql}",
228
                $contextparams);
229
    }
230
 
231
    /**
232
     * Get the filter options.
233
     *
234
     * This is shared to allow unit testing too.
235
     *
236
     * @return  \stdClass
237
     */
238
    public static function get_filter_options() {
239
        return (object) [
240
            'overflowdiv' => true,
241
            'noclean' => true,
242
        ];
243
    }
244
}