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 report_stats.
19
 *
20
 * @package    report_stats
21
 * @copyright  2018 Zig Tan <zig@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace report_stats\privacy;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
use \core_privacy\local\metadata\collection;
30
use \core_privacy\local\request\contextlist;
31
use \core_privacy\local\request\approved_contextlist;
32
use \core_privacy\local\request\userlist;
33
use \core_privacy\local\request\approved_userlist;
34
 
35
/**
36
 * Privacy Subsystem for report_stats implementing provider.
37
 *
38
 * @copyright  2018 Zig Tan <zig@moodle.com>
39
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
 */
41
class provider implements
42
        \core_privacy\local\metadata\provider,
43
        \core_privacy\local\request\core_userlist_provider,
44
        \core_privacy\local\request\subsystem\provider{
45
 
46
    /**
47
     * Returns information about the user data stored in this component.
48
     *
49
     * @param  collection $collection A list of information about this component
50
     * @return collection The collection object filled out with information about this component.
51
     */
52
    public static function get_metadata(collection $collection): collection {
53
        $statsuserdaily = [
54
            'courseid' => 'privacy:metadata:courseid',
55
            'userid' => 'privacy:metadata:userid',
56
            'roleid' => 'privacy:metadata:roleid',
57
            'timeend' => 'privacy:metadata:timeend',
58
            'statsreads' => 'privacy:metadata:statsreads',
59
            'statswrites' => 'privacy:metadata:statswrites',
60
            'stattype' => 'privacy:metadata:stattype'
61
        ];
62
 
63
        $statsuserweekly = [
64
            'courseid' => 'privacy:metadata:courseid',
65
            'userid' => 'privacy:metadata:userid',
66
            'roleid' => 'privacy:metadata:roleid',
67
            'timeend' => 'privacy:metadata:timeend',
68
            'statsreads' => 'privacy:metadata:statsreads',
69
            'statswrites' => 'privacy:metadata:statswrites',
70
            'stattype' => 'privacy:metadata:stattype'
71
        ];
72
 
73
        $statsusermonthly = [
74
            'courseid' => 'privacy:metadata:courseid',
75
            'userid' => 'privacy:metadata:userid',
76
            'roleid' => 'privacy:metadata:roleid',
77
            'timeend' => 'privacy:metadata:timeend',
78
            'statsreads' => 'privacy:metadata:statsreads',
79
            'statswrites' => 'privacy:metadata:statswrites',
80
            'stattype' => 'privacy:metadata:stattype'
81
        ];
82
        $collection->add_database_table('stats_user_daily', $statsuserdaily, 'privacy:metadata:statssummary');
83
        $collection->add_database_table('stats_user_weekly', $statsuserweekly, 'privacy:metadata:statssummary');
84
        $collection->add_database_table('stats_user_monthly', $statsusermonthly, 'privacy:metadata:statssummary');
85
        return $collection;
86
    }
87
 
88
    /**
89
     * Get the list of contexts that contain user information for the specified user.
90
     *
91
     * @param   int $userid The user to search.
92
     * @return  contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
93
     */
94
    public static function get_contexts_for_userid(int $userid): contextlist {
95
        $params = ['userid' => $userid, 'contextcourse' => CONTEXT_COURSE];
96
        $sql = "SELECT ctx.id
97
                FROM {context} ctx
98
                JOIN {stats_user_daily} sud ON sud.courseid = ctx.instanceid AND sud.userid = :userid
99
                WHERE ctx.contextlevel = :contextcourse";
100
 
101
        $contextlist = new contextlist();
102
        $contextlist->add_from_sql($sql, $params);
103
 
104
        $sql = "SELECT ctx.id
105
                FROM {context} ctx
106
                JOIN {stats_user_weekly} suw ON suw.courseid = ctx.instanceid AND suw.userid = :userid
107
                WHERE ctx.contextlevel = :contextcourse";
108
        $contextlist->add_from_sql($sql, $params);
109
 
110
        $sql = "SELECT ctx.id
111
                FROM {context} ctx
112
                JOIN {stats_user_monthly} sum ON sum.courseid = ctx.instanceid AND sum.userid = :userid
113
                WHERE ctx.contextlevel = :contextcourse";
114
        $contextlist->add_from_sql($sql, $params);
115
 
116
        return $contextlist;
117
    }
118
 
119
    /**
120
     * Get the list of users within a specific context.
121
     *
122
     * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
123
     */
124
    public static function get_users_in_context(userlist $userlist) {
125
        $context = $userlist->get_context();
126
 
127
        if (!$context instanceof \context_course) {
128
            return;
129
        }
130
 
131
        $params = ['courseid' => $context->instanceid];
132
 
133
        $sql = "SELECT userid FROM {stats_user_daily} WHERE courseid = :courseid";
134
        $userlist->add_from_sql('userid', $sql, $params);
135
 
136
        $sql = "SELECT userid FROM {stats_user_weekly} WHERE courseid = :courseid";
137
        $userlist->add_from_sql('userid', $sql, $params);
138
 
139
        $sql = "SELECT userid FROM {stats_user_monthly} WHERE courseid = :courseid";
140
        $userlist->add_from_sql('userid', $sql, $params);
141
    }
142
 
143
    /**
144
     * Export all user data for the specified user, in the specified contexts.
145
     *
146
     * @param approved_contextlist $contextlist The approved contexts to export information for.
147
     */
148
    public static function export_user_data(approved_contextlist $contextlist) {
149
        global $DB;
150
 
151
        // Some sneeky person might have sent us the wrong context list. We should check.
152
        if ($contextlist->get_component() != 'report_stats') {
153
            return;
154
        }
155
 
156
        // Got to check that someone hasn't foolishly added a context between creating the context list and then filtering down
157
        // to an approved context.
158
        $contexts = array_filter($contextlist->get_contexts(), function($context) {
159
            if ($context->contextlevel == CONTEXT_COURSE) {
160
                return $context;
161
            }
162
        });
163
 
164
        $tables = [
165
            'stats_user_daily' => get_string('privacy:dailypath', 'report_stats'),
166
            'stats_user_weekly' => get_string('privacy:weeklypath', 'report_stats'),
167
            'stats_user_monthly' => get_string('privacy:monthlypath', 'report_stats')
168
        ];
169
 
170
        $courseids = array_map(function($context) {
171
            return $context->instanceid;
172
        }, $contexts);
173
 
174
        foreach ($tables as $table => $path) {
175
 
176
            list($insql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
177
            $sql = "SELECT s.id, c.fullname, s.roleid, s.timeend, s.statsreads, s.statswrites, s.stattype, c.id as courseid
178
                      FROM {" . $table . "} s
179
                      JOIN {course} c ON s.courseid = c.id
180
                     WHERE s.userid = :userid AND c.id $insql
181
                     ORDER BY c.id ASC";
182
            $params['userid'] = $contextlist->get_user()->id;
183
            $records = $DB->get_records_sql($sql, $params);
184
 
185
            $statsrecords = [];
186
            foreach ($records as $record) {
187
                $context = \context_course::instance($record->courseid);
188
                if (!isset($statsrecords[$record->courseid])) {
189
                    $statsrecords[$record->courseid] = new \stdClass();
190
                    $statsrecords[$record->courseid]->context = $context;
191
                }
192
                $statsrecords[$record->courseid]->entries[] = [
193
                    'course' => format_string($record->fullname, true, ['context' => $context]),
194
                    'roleid' => $record->roleid,
195
                    'timeend' => \core_privacy\local\request\transform::datetime($record->timeend),
196
                    'statsreads' => $record->statsreads,
197
                    'statswrites' => $record->statswrites,
198
                    'stattype' => $record->stattype
199
                ];
200
            }
201
            foreach ($statsrecords as $coursestats) {
202
                \core_privacy\local\request\writer::with_context($coursestats->context)->export_data([$path],
203
                        (object) $coursestats->entries);
204
            }
205
        }
206
    }
207
 
208
    /**
209
     * Delete all data for all users in the specified context.
210
     *
211
     * @param context $context The specific context to delete data for.
212
     */
213
    public static function delete_data_for_all_users_in_context(\context $context) {
214
        // Check that this context is a course context.
215
        if ($context->contextlevel == CONTEXT_COURSE) {
216
            static::delete_stats($context->instanceid);
217
        }
218
    }
219
 
220
    /**
221
     * Delete all user data for the specified user, in the specified contexts.
222
     *
223
     * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
224
     */
225
    public static function delete_data_for_user(approved_contextlist $contextlist) {
226
        if ($contextlist->get_component() != 'report_stats') {
227
            return;
228
        }
229
        foreach ($contextlist->get_contexts() as $context) {
230
            if ($context->contextlevel == CONTEXT_COURSE) {
231
                static::delete_stats($context->instanceid, $contextlist->get_user()->id);
232
            }
233
        }
234
    }
235
 
236
    /**
237
     * Delete multiple users within a single context.
238
     *
239
     * @param approved_userlist $userlist The approved context and user information to delete information for.
240
     */
241
    public static function delete_data_for_users(approved_userlist $userlist) {
242
        global $DB;
243
 
244
        $context = $userlist->get_context();
245
 
246
        if ($context instanceof \context_course) {
247
            list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
248
            $select = "courseid = :courseid AND userid {$usersql}";
249
            $params = ['courseid' => $context->instanceid] + $userparams;
250
 
251
            $DB->delete_records_select('stats_user_daily', $select, $params);
252
            $DB->delete_records_select('stats_user_weekly', $select, $params);
253
            $DB->delete_records_select('stats_user_monthly', $select, $params);
254
        }
255
    }
256
 
257
    /**
258
     * Deletes stats for a given course.
259
     *
260
     * @param int $courseid The course ID to delete the stats for.
261
     * @param int $userid Optionally a user id to delete records with.
262
     */
263
    protected static function delete_stats(int $courseid, int $userid = null) {
264
        global $DB;
265
        $params = (isset($userid)) ? ['courseid' => $courseid, 'userid' => $userid] : ['courseid' => $courseid];
266
        $DB->delete_records('stats_user_daily', $params);
267
        $DB->delete_records('stats_user_weekly', $params);
268
        $DB->delete_records('stats_user_monthly', $params);
269
    }
270
}