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
 * mod_reengagement Data provider.
19
 *
20
 * @package    mod_reengagement
21
 * @copyright  2018 Catalyst IT
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace mod_reengagement\privacy;
26
 
27
use context;
28
use context_module;
29
use core_privacy\local\metadata\collection;
30
use core_privacy\local\request\approved_contextlist;
31
use core_privacy\local\request\approved_userlist;
32
use core_privacy\local\request\contextlist;
33
use core_privacy\local\request\transform;
34
use core_privacy\local\request\userlist;
35
use core_privacy\local\request\writer;
36
use stdClass;
37
 
38
/**
39
 * Data provider for mod_reengagement.
40
 *
41
 * @copyright 2018 Catalyst IT
42
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43
 */
44
class provider implements
45
    \core_privacy\local\metadata\provider,
46
    \core_privacy\local\request\core_userlist_provider,
47
    \core_privacy\local\request\plugin\provider {
48
 
49
    /**
50
     * Returns meta data about this system.
51
     *
52
     * @param collection $collection The initialised collection to add items to.
53
     * @return collection A listing of user data stored through this system.
54
     */
55
    public static function get_metadata(collection $collection) : collection {
56
        $collection->add_database_table(
57
            'reengagement_inprogress',
58
            [
59
                'reengagement' => 'privacy:metadata:reengagement',
60
                'userid' => 'privacy:metadata:userid',
61
                'completiontime' => 'privacy:metadata:completiontime',
62
                'emailtime' => 'privacy:metadata:emailtime',
63
                'emailsent' => 'privacy:metadata:emailsent'
64
            ],
65
            'privacy:metadata:reengagement_inprogress'
66
        );
67
 
68
        return $collection;
69
    }
70
 
71
    /**
72
     * Get the list of contexts that contain user information for the specified user.
73
     *
74
     * @param int $userid The user to search.
75
     * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
76
     */
77
    public static function get_contexts_for_userid(int $userid) : contextlist {
78
        return (new contextlist)->add_from_sql(
79
            "SELECT ctx.id
80
                 FROM {course_modules} cm
81
                 JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
82
                 JOIN {reengagement} r ON cm.instance = r.id
83
                 JOIN {reengagement_inprogress} rip ON rip.reengagement = r.id
84
                 JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
85
                 WHERE rip.userid = :userid",
86
            [
87
                'modulename' => 'reengagement',
88
                'contextlevel' => CONTEXT_MODULE,
89
                'userid' => $userid
90
            ]
91
        );
92
    }
93
 
94
    /**
95
     * Delete all data for all users in the specified context.
96
     *
97
     * @param context $context The specific context to delete data for.
98
     */
99
    public static function delete_data_for_all_users_in_context(context $context) {
100
        global $DB;
101
 
102
        if (!$context instanceof context_module) {
103
            return;
104
        }
105
 
106
        if (!$cm = get_coursemodule_from_id('reengagement', $context->instanceid)) {
107
            return;
108
        }
109
 
110
        // Delete all information recorded against sessions associated with this module.
111
        $DB->delete_records_select(
112
            'reengagement_inprogress',
113
            "reengagement = :reengagementid",
114
            [
115
                'reengagementid' => $cm->instance
116
            ]
117
        );
118
    }
119
 
120
    /**
121
     * Delete all user data for the specified user, in the specified contexts.
122
     *
123
     * @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
124
     */
125
    public static function delete_data_for_user(approved_contextlist $contextlist) {
126
        global $DB;
127
        $userid = (int)$contextlist->get_user()->id;
128
 
129
        foreach ($contextlist as $context) {
130
            if (!$context instanceof context_module) {
131
                continue;
132
            }
133
 
134
            if (!$cm = get_coursemodule_from_id('reengagement', $context->instanceid)) {
135
                continue;
136
            }
137
 
138
            $DB->delete_records_select(
139
                'reengagement_inprogress',
140
                "reengagement = :reengagementid AND userid = :userid",
141
                [
142
                    'reengagementid' => $cm->instance,
143
                    'userid' => $userid
144
                ]
145
            );
146
        }
147
    }
148
 
149
    /**
150
     * Export all user data for the specified user, in the specified contexts.
151
     *
152
     * @param approved_contextlist $contextlist The approved contexts to export information for.
153
     */
154
    public static function export_user_data(approved_contextlist $contextlist) {
155
        global $DB;
156
 
157
        $params = [
158
            'modulename' => 'reengagement',
159
            'contextlevel' => CONTEXT_MODULE,
160
            'userid' => $contextlist->get_user()->id
161
        ];
162
 
163
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
164
 
165
        $sql = "SELECT
166
                    rip.*,
167
                    ctx.id as contextid,
168
                    r.name as reengagementname
169
                    FROM {course_modules} cm
170
                    JOIN {reengagement} r ON cm.instance = r.id
171
                    JOIN {reengagement_inprogress} rip ON rip.reengagement = r.id
172
                    JOIN {context} ctx ON cm.id = ctx.instanceid
173
                    WHERE rip.userid = :userid AND (ctx.id {$contextsql})";
174
 
175
        $reengagements = $DB->get_records_sql($sql, $params + $contextparams);
176
 
177
        $bycontext = self::group_by_property($reengagements, 'contextid');
178
 
179
        foreach ($bycontext as $contextid => $sessions) {
180
            $context = context::instance_by_id($contextid);
181
            $sessionsbyid = self::group_by_property($sessions, 'reengagement');
182
 
183
            foreach ($sessionsbyid as $sessionid => $sessions) {
184
                writer::with_context($context)->export_data(
185
                    [get_string('reengagement', 'reengagement') . ' ' . $sessionid],
186
                    (object)[array_map([self::class, 'transform_db_row_to_data'], $sessions)]
187
                );
188
            };
189
        }
190
    }
191
 
192
    /**
193
     * Helper function to group an array of stdClasses by a common property.
194
     *
195
     * @param array $classes An array of classes to group.
196
     * @param string $property A common property to group the classes by.
197
     */
198
    private static function group_by_property(array $classes, string $property) : array {
199
        return array_reduce(
200
            $classes,
201
            function (array $classes, stdClass $class) use ($property) : array {
202
                $classes[$class->{$property}][] = $class;
203
                return $classes;
204
            },
205
            []
206
        );
207
    }
208
 
209
    /**
210
     * Helper function to transform a row from the database in to session data to export.
211
     *
212
     * The properties of the "dbrow" are very specific to the result of the SQL from
213
     * the export_user_data function.
214
     *
215
     * @param stdClass $dbrow A row from the database containing session information.
216
     * @return stdClass The transformed row.
217
     */
218
    private static function transform_db_row_to_data(stdClass $dbrow) : stdClass {
219
        return (object) [
220
            'name' => $dbrow->reengagementname,
221
            'userid' => $dbrow->userid,
222
            'completiontime' => transform::datetime($dbrow->completiontime),
223
            'emailtime' => transform::datetime($dbrow->emailtime),
224
            'emailsent' => $dbrow->emailsent,
225
            'completed' => $dbrow->completed
226
        ];
227
    }
228
 
229
    /**
230
     * Get the list of users who have data within a context.
231
     *
232
     * @param   userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
233
     */
234
    public static function get_users_in_context(userlist $userlist) {
235
        $context = $userlist->get_context();
236
 
237
        if (!is_a($context, \context_module::class)) {
238
            return;
239
        }
240
        $sql = "SELECT r.userid
241
                  FROM {reengagement_inprogress} r
242
                  JOIN {modules} m
243
                    ON m.name = 'reengagement'
244
                  JOIN {course_modules} cm
245
                    ON cm.instance = r.reengagement
246
                   AND cm.module = m.id
247
                  JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
248
                 WHERE ctx.id = :contextid";
249
 
250
        $params = [
251
            'contextlevel' => CONTEXT_MODULE,
252
            'contextid'    => $context->id,
253
        ];
254
 
255
        $userlist->add_from_sql('userid', $sql, $params);
256
    }
257
 
258
    /**
259
     * Delete multiple users within a single context.
260
     *
261
     * @param   approved_userlist       $userlist The approved context and user information to delete information for.
262
     */
263
    public static function delete_data_for_users(approved_userlist $userlist) {
264
        global $DB;
265
        $context = $userlist->get_context();
266
 
267
        if (!is_a($context, \context_module::class)) {
268
            return;
269
        }
270
        // Prepare SQL to gather all completed IDs.
271
        $userids = $userlist->get_userids();
272
        list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
273
 
274
        $sql = "(SELECT r.id
275
                  FROM {reengagement_inprogress} r
276
                  JOIN {modules} m
277
                    ON m.name = 'reengagement'
278
                  JOIN {course_modules} cm
279
                    ON cm.instance = r.reengagement
280
                   AND cm.module = m.id
281
                  JOIN {context} ctx
282
                    ON ctx.instanceid = cm.id
283
                 WHERE ctx.id = :contextid
284
                   AND r.userid $insql)";
285
        $params = array_merge($inparams, ['contextid' => $context->id]);
286
 
287
        $DB->delete_records_select('reengagement_inprogress', "id $sql", $params);
288
    }
289
}