Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
declare(strict_types=1);
18
 
19
namespace core_reportbuilder\privacy;
20
 
21
use context;
22
use stdClass;
23
use core_privacy\local\metadata\collection;
24
use core_privacy\local\request\approved_contextlist;
25
use core_privacy\local\request\approved_userlist;
26
use core_privacy\local\request\contextlist;
27
use core_privacy\local\request\core_userlist_provider;
28
use core_privacy\local\request\transform;
29
use core_privacy\local\request\userlist;
30
use core_privacy\local\request\writer;
31
use core_reportbuilder\manager;
32
use core_reportbuilder\local\helpers\schedule as schedule_helper;
1441 ariadna 33
use core_reportbuilder\local\models\{audience, column, filter, report, schedule, user_filter};
1 efrain 34
 
35
/**
36
 * Privacy Subsystem for core_reportbuilder
37
 *
38
 * @package     core_reportbuilder
39
 * @copyright   2021 David Matamoros <davidmc@moodle.com>
40
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41
 */
42
class provider implements
43
    \core_privacy\local\metadata\provider,
44
    \core_privacy\local\request\plugin\provider,
1441 ariadna 45
    core_userlist_provider {
1 efrain 46
 
47
    /**
48
     * Returns metadata about the component
49
     *
50
     * @param collection $collection
51
     * @return collection
52
     */
53
    public static function get_metadata(collection $collection): collection {
54
        $collection->add_database_table(report::TABLE, [
55
            'name' => 'privacy:metadata:report:name',
56
            'source' => 'privacy:metadata:report:source',
57
            'conditiondata' => 'privacy:metadata:report:conditiondata',
58
            'settingsdata' => 'privacy:metadata:report:settingsdata',
59
            'uniquerows' => 'privacy:metadata:report:uniquerows',
60
            'usercreated' => 'privacy:metadata:report:usercreated',
61
            'usermodified' => 'privacy:metadata:report:usermodified',
62
            'timecreated' => 'privacy:metadata:report:timecreated',
63
            'timemodified' => 'privacy:metadata:report:timemodified',
64
        ], 'privacy:metadata:report');
65
 
66
        $collection->add_database_table(column::TABLE, [
67
            'uniqueidentifier' => 'privacy:metadata:column:uniqueidentifier',
68
            'usercreated' => 'privacy:metadata:column:usercreated',
69
            'usermodified' => 'privacy:metadata:column:usermodified',
70
        ], 'privacy:metadata:column');
71
 
72
        $collection->add_database_table(filter::TABLE, [
73
            'uniqueidentifier' => 'privacy:metadata:filter:uniqueidentifier',
74
            'usercreated' => 'privacy:metadata:filter:usercreated',
75
            'usermodified' => 'privacy:metadata:filter:usermodified',
76
        ], 'privacy:metadata:filter');
77
 
1441 ariadna 78
        $collection->add_database_table(user_filter::TABLE, [
79
            'filterdata' => 'privacy:metadata:user_filter:filterdata',
80
            'timecreated' => 'privacy:metadata:user_filter:timecreated',
81
            'timemodified' => 'privacy:metadata:user_filter:timemodified',
82
        ], 'privacy:metadata:user_filter');
83
 
1 efrain 84
        $collection->add_database_table(audience::TABLE, [
85
            'classname' => 'privacy:metadata:audience:classname',
86
            'configdata' => 'privacy:metadata:audience:configdata',
87
            'heading' => 'privacy:metadata:audience:heading',
88
            'usercreated' => 'privacy:metadata:audience:usercreated',
89
            'usermodified' => 'privacy:metadata:audience:usermodified',
90
            'timecreated' => 'privacy:metadata:audience:timecreated',
91
            'timemodified' => 'privacy:metadata:audience:timemodified',
92
        ], 'privacy:metadata:audience');
93
 
94
        $collection->add_database_table(schedule::TABLE, [
95
            'name' => 'privacy:metadata:schedule:name',
96
            'enabled' => 'privacy:metadata:schedule:enabled',
97
            'audiences' => 'privacy:metadata:schedule:audiences',
98
            'format' => 'privacy:metadata:schedule:format',
99
            'subject' => 'privacy:metadata:schedule:subject',
100
            'message' => 'privacy:metadata:schedule:message',
101
            'userviewas' => 'privacy:metadata:schedule:userviewas',
102
            'timescheduled' => 'privacy:metadata:schedule:timescheduled',
103
            'recurrence' => 'privacy:metadata:schedule:recurrence',
104
            'reportempty' => 'privacy:metadata:schedule:reportempty',
105
            'usercreated' => 'privacy:metadata:schedule:usercreated',
106
            'usermodified' => 'privacy:metadata:schedule:usermodified',
107
            'timecreated' => 'privacy:metadata:schedule:timecreated',
108
            'timemodified' => 'privacy:metadata:schedule:timemodified',
109
        ], 'privacy:metadata:schedule');
110
 
111
        return $collection;
112
    }
113
 
114
    /**
115
     * Get export sub context for a report
116
     *
117
     * @param report $report
118
     * @return array
119
     */
120
    public static function get_export_subcontext(report $report): array {
121
        $reportnode = implode('-', [
122
            $report->get('id'),
123
            clean_filename($report->get_formatted_name()),
124
        ]);
125
 
126
        return [get_string('reportbuilder', 'core_reportbuilder'), $reportnode];
127
    }
128
 
129
    /**
130
     * Get the list of contexts that contain user information for the specified user
131
     *
132
     * @param int $userid
133
     * @return contextlist
134
     */
135
    public static function get_contexts_for_userid(int $userid): contextlist {
136
        $contextlist = new contextlist();
137
 
1441 ariadna 138
        // Locate all contexts for reports the user has created, or reports they have created ancillary data for.
1 efrain 139
        $sql = '
140
            SELECT r.contextid
141
              FROM {' . report::TABLE . '} r
142
             WHERE r.type = 0
143
               AND (r.usercreated = ?
144
                 OR r.usermodified = ?
145
                 OR r.id IN (
1441 ariadna 146
                    SELECT f.reportid
147
                      FROM {' . user_filter::TABLE . '} f
148
                     WHERE f.usercreated = ?
149
                     UNION
1 efrain 150
                    SELECT a.reportid
151
                      FROM {' . audience::TABLE . '} a
152
                     WHERE a.usercreated = ? OR a.usermodified = ?
153
                     UNION
154
                    SELECT s.reportid
155
                      FROM {' . schedule::TABLE . '} s
156
                     WHERE s.usercreated = ? OR s.usermodified = ?
157
                    )
158
                   )';
159
 
1441 ariadna 160
        return $contextlist->add_from_sql($sql, array_fill(0, 7, $userid));
1 efrain 161
    }
162
 
163
    /**
164
     * Get users in context
165
     *
166
     * @param userlist $userlist
167
     */
168
    public static function get_users_in_context(userlist $userlist): void {
169
        $select = 'r.type = :type AND r.contextid = :contextid';
170
        $params = ['type' => 0, 'contextid' => $userlist->get_context()->id];
171
 
172
        // Users who have created reports.
173
        $sql = 'SELECT r.usercreated, r.usermodified
174
                 FROM {' . report::TABLE . '} r
175
                WHERE ' . $select;
176
        $userlist->add_from_sql('usercreated', $sql, $params);
177
        $userlist->add_from_sql('usermodified', $sql, $params);
178
 
1441 ariadna 179
        // Users who have created user filters.
180
        $sql = 'SELECT f.usercreated
181
                  FROM {' . user_filter::TABLE . '} f
182
                  JOIN {' . report::TABLE . '} r ON r.id = f.reportid
183
                WHERE ' . $select;
184
        $userlist->add_from_sql('usercreated', $sql, $params);
185
 
1 efrain 186
        // Users who have created audiences.
187
        $sql = 'SELECT a.usercreated, a.usermodified
188
                  FROM {' . audience::TABLE . '} a
189
                  JOIN {' . report::TABLE . '} r ON r.id = a.reportid
190
                WHERE ' . $select;
191
        $userlist->add_from_sql('usercreated', $sql, $params);
192
        $userlist->add_from_sql('usermodified', $sql, $params);
193
 
194
        // Users who have created schedules.
195
        $sql = 'SELECT s.usercreated, s.usermodified
196
                  FROM {' . schedule::TABLE . '} s
197
                  JOIN {' . report::TABLE . '} r ON r.id = s.reportid
198
                 WHERE ' . $select;
199
        $userlist->add_from_sql('usercreated', $sql, $params);
200
        $userlist->add_from_sql('usermodified', $sql, $params);
201
    }
202
 
203
    /**
204
     * Export all user data for the specified user in the specified contexts
205
     *
206
     * @param approved_contextlist $contextlist
207
     */
208
    public static function export_user_data(approved_contextlist $contextlist): void {
209
        if (empty($contextlist->count())) {
210
            return;
211
        }
212
 
213
        $user = $contextlist->get_user();
214
 
215
        // We need to get all reports that the user has created, or reports they have created audience/schedules for.
216
        $select = 'type = 0 AND (usercreated = ? OR usermodified = ? OR id IN (
1441 ariadna 217
            SELECT f.reportid
218
              FROM {' . user_filter::TABLE . '} f
219
             WHERE f.usercreated = ?
220
             UNION
1 efrain 221
            SELECT a.reportid
222
              FROM {' . audience::TABLE . '} a
223
             WHERE a.usercreated = ? OR a.usermodified = ?
224
             UNION
225
            SELECT s.reportid
226
              FROM {' . schedule::TABLE . '} s
227
             WHERE s.usercreated = ? OR s.usermodified = ?
228
        ))';
1441 ariadna 229
        $params = array_fill(0, 7, $user->id);
1 efrain 230
 
231
        foreach (report::get_records_select($select, $params) as $report) {
232
            $subcontext = static::get_export_subcontext($report);
233
 
234
            self::export_report($subcontext, $report);
235
 
1441 ariadna 236
            // User filters.
237
            if ($userfilters = user_filter::get_records(['reportid' => $report->get('id'), 'usercreated' => $user->id])) {
238
                static::export_user_filters($report->get_context(), $subcontext, $userfilters);
239
            }
240
 
1 efrain 241
            $select = 'reportid = ? AND (usercreated = ? OR usermodified = ?)';
242
            $params = [$report->get('id'), $user->id, $user->id];
243
 
244
            // Audiences.
245
            if ($audiences = audience::get_records_select($select, $params)) {
246
                static::export_audiences($report->get_context(), $subcontext, $audiences);
247
            }
248
 
249
            // Schedules.
250
            if ($schedules = schedule::get_records_select($select, $params)) {
251
                static::export_schedules($report->get_context(), $subcontext, $schedules);
252
            }
253
        }
254
    }
255
 
256
    /**
257
     * Delete data for all users in context
258
     *
259
     * @param context $context
260
     */
261
    public static function delete_data_for_all_users_in_context(context $context): void {
262
        // We don't perform any deletion of user data.
263
    }
264
 
265
    /**
266
     * Delete data for user
267
     *
268
     * @param approved_contextlist $contextlist
269
     */
270
    public static function delete_data_for_user(approved_contextlist $contextlist): void {
271
        // We don't perform any deletion of user data.
272
    }
273
 
274
    /**
275
     * Delete data for users
276
     *
277
     * @param approved_userlist $userlist
278
     */
279
    public static function delete_data_for_users(approved_userlist $userlist): void {
280
        // We don't perform any deletion of user data.
281
    }
282
 
283
    /**
284
     * Export given report in context
285
     *
286
     * @param array $subcontext
287
     * @param report $report
288
     */
289
    protected static function export_report(array $subcontext, report $report): void {
290
        // Show the source name, if it exists.
291
        $source = $report->get('source');
292
        if (manager::report_source_exists($source)) {
293
            $source = call_user_func([$source, 'get_name']);
294
        }
295
 
296
        $reportdata = (object) [
297
            'name' => $report->get_formatted_name(),
298
            'source' => $source,
299
            'conditiondata' => $report->get('conditiondata'),
300
            'settingsdata' => $report->get('settingsdata'),
301
            'uniquerows' => transform::yesno($report->get('uniquerows')),
302
            'usercreated' => transform::user($report->get('usercreated')),
303
            'usermodified' => transform::user($report->get('usermodified')),
304
            'timecreated' => transform::datetime($report->get('timecreated')),
305
            'timemodified' => transform::datetime($report->get('timemodified')),
306
        ];
307
 
308
        writer::with_context($report->get_context())->export_data($subcontext, $reportdata);
309
    }
310
 
311
    /**
1441 ariadna 312
     * Export given user filters in context
313
     *
314
     * @param context $context
315
     * @param array $subcontext
316
     * @param user_filter[] $userfilters
317
     */
318
    protected static function export_user_filters(context $context, array $subcontext, array $userfilters): void {
319
        $userfilterdata = array_map(static function(user_filter $userfilter): stdClass {
320
            return (object) [
321
                'filterdata' => $userfilter->get('filterdata'),
322
                'timecreated' => transform::datetime($userfilter->get('timecreated')),
323
                'timemodified' => transform::datetime($userfilter->get('timemodified')),
324
            ];
325
        }, $userfilters);
326
 
327
        writer::with_context($context)->export_related_data($subcontext, 'userfilters', (object) ['data' => $userfilterdata]);
328
    }
329
 
330
    /**
1 efrain 331
     * Export given audiences in context
332
     *
333
     * @param context $context
334
     * @param array $subcontext
335
     * @param audience[] $audiences
336
     */
337
    protected static function export_audiences(context $context, array $subcontext, array $audiences): void {
338
        $audiencedata = array_map(static function(audience $audience) use ($context): stdClass {
339
            // Show the audience name, if it exists.
340
            $classname = $audience->get('classname');
341
            if (class_exists($classname)) {
342
                $classname = $classname::instance()->get_name();
343
            }
344
 
345
            return (object) [
346
                'classname' => $classname,
347
                'heading' => $audience->get_formatted_heading($context),
348
                'configdata' => $audience->get('configdata'),
349
                'usercreated' => transform::user($audience->get('usercreated')),
350
                'usermodified' => transform::user($audience->get('usermodified')),
351
                'timecreated' => transform::datetime($audience->get('timecreated')),
352
                'timemodified' => transform::datetime($audience->get('timemodified')),
353
            ];
354
        }, $audiences);
355
 
356
        writer::with_context($context)->export_related_data($subcontext, 'audiences', (object) ['data' => $audiencedata]);
357
    }
358
 
359
    /**
360
     * Export given schedules in context
361
     *
362
     * @param context $context
363
     * @param array $subcontext
364
     * @param schedule[] $schedules
365
     */
366
    protected static function export_schedules(context $context, array $subcontext, array $schedules): void {
367
        $formatoptions = schedule_helper::get_format_options();
368
        $recurrenceoptions = schedule_helper::get_recurrence_options();
369
        $viewasoptions = schedule_helper::get_viewas_options();
370
        $reportemptyoptions = schedule_helper::get_report_empty_options();
371
 
372
        $scheduledata = array_map(static function(schedule $schedule) use (
373
                $context, $formatoptions, $recurrenceoptions, $viewasoptions, $reportemptyoptions): stdClass {
374
 
375
            // The "User view as" property will be either creator, recipient or a specific userid.
376
            $userviewas = $schedule->get('userviewas');
377
 
378
            return (object) [
379
                'name' => $schedule->get_formatted_name($context),
380
                'enabled' => transform::yesno($schedule->get('enabled')),
381
                'format' => $formatoptions[$schedule->get('format')],
382
                'timescheduled' => transform::datetime($schedule->get('timescheduled')),
383
                'recurrence' => $recurrenceoptions[$schedule->get('recurrence')],
384
                'userviewas' => $viewasoptions[$userviewas] ?? transform::user($userviewas),
385
                'audiences' => $schedule->get('audiences'),
386
                'subject' => $schedule->get('subject'),
387
                'message' => format_text($schedule->get('message'), $schedule->get('messageformat'), ['context' => $context]),
388
                'reportempty' => $reportemptyoptions[$schedule->get('reportempty')],
389
                'usercreated' => transform::user($schedule->get('usercreated')),
390
                'usermodified' => transform::user($schedule->get('usermodified')),
391
                'timecreated' => transform::datetime($schedule->get('timecreated')),
392
                'timemodified' => transform::datetime($schedule->get('timemodified')),
393
            ];
394
        }, $schedules);
395
 
396
        writer::with_context($context)->export_related_data($subcontext, 'schedules', (object) ['data' => $scheduledata]);
397
    }
398
}