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