MDL-62289 tool_dataprivacy: Ensure all user data deleted.
[moodle.git] / admin / tool / dataprivacy / tests / expired_contexts_test.php
CommitLineData
5efc1f9e
DM
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 * Expired contexts tests.
19 *
20 * @package tool_dataprivacy
21 * @copyright 2018 David Monllao
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25use tool_dataprivacy\api;
26use tool_dataprivacy\data_registry;
27use tool_dataprivacy\expired_context;
28
29defined('MOODLE_INTERNAL') || die();
30global $CFG;
31
32/**
33 * Expired contexts tests.
34 *
35 * @package tool_dataprivacy
36 * @copyright 2018 David Monllao
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 */
39class tool_dataprivacy_expired_contexts_testcase extends advanced_testcase {
40
41 /**
42 * setUp.
43 */
44 public function setUp() {
45 $this->resetAfterTest();
46 $this->setAdminUser();
47 }
48
49 /**
50 * Test expired users flagging and deletion.
51 *
52 * @return null
53 */
54 public function test_expired_users() {
55 global $DB;
56
0462786a 57 $purpose = api::create_purpose((object)['name' => 'p1', 'retentionperiod' => 'PT1H', 'lawfulbases' => 'gdpr_art_6_1_a']);
5efc1f9e
DM
58 $cat = api::create_category((object)['name' => 'a']);
59
60 $record = (object)[
61 'purposeid' => $purpose->get('id'),
62 'categoryid' => $cat->get('id'),
63 'contextlevel' => CONTEXT_SYSTEM,
64 ];
65 api::set_contextlevel($record);
66 $record->contextlevel = CONTEXT_USER;
67 api::set_contextlevel($record);
68
69 $userdata = ['lastaccess' => '123'];
70 $user1 = $this->getDataGenerator()->create_user($userdata);
71 $user2 = $this->getDataGenerator()->create_user($userdata);
72 $user3 = $this->getDataGenerator()->create_user($userdata);
73 $user4 = $this->getDataGenerator()->create_user($userdata);
74 $user5 = $this->getDataGenerator()->create_user();
75
76 $course1 = $this->getDataGenerator()->create_course();
77 // Old course.
78 $course2 = $this->getDataGenerator()->create_course(['startdate' => '1', 'enddate' => '2']);
79 // Ongoing course.
e60058ff 80 $course3 = $this->getDataGenerator()->create_course(['startdate' => '1', 'enddate' => time() + YEARSECS]);
5efc1f9e
DM
81
82 $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
83 $this->getDataGenerator()->enrol_user($user2->id, $course2->id, 'student');
84 $this->getDataGenerator()->enrol_user($user3->id, $course2->id, 'student');
85 $this->getDataGenerator()->enrol_user($user4->id, $course3->id, 'student');
86
c8e49221
AG
87 // Add an activity and some data for user 2.
88 $assignmod = $this->getDataGenerator()->create_module('assign', ['course' => $course2->id]);
89 $data = (object) [
90 'assignment' => $assignmod->id,
91 'userid' => $user2->id,
92 'timecreated' => time(),
93 'timemodified' => time(),
94 'status' => 'new',
95 'groupid' => 0,
96 'attemptnumber' => 0,
97 'latest' => 1,
98 ];
99 $DB->insert_record('assign_submission', $data);
100 // We should have one record in the assign submission table.
101 $this->assertEquals(1, $DB->count_records('assign_submission'));
102
5efc1f9e
DM
103 // Users without lastaccess are skipped as well as users enroled in courses with no end date.
104 $expired = new \tool_dataprivacy\expired_user_contexts();
105 $numexpired = $expired->flag_expired();
106 $this->assertEquals(2, $numexpired);
107 $this->assertEquals(2, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_EXPIRED]));
108
e60058ff 109 // Approve user2 to be deleted.
5efc1f9e
DM
110 $user2ctx = \context_user::instance($user2->id);
111 $expiredctx = expired_context::get_record(['contextid' => $user2ctx->id]);
112 api::set_expired_context_status($expiredctx, expired_context::STATUS_APPROVED);
113 $this->assertEquals(1, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_APPROVED]));
114
115 // Delete expired contexts.
116 $deleted = $expired->delete();
117 $this->assertEquals(1, $deleted);
118 $this->assertEquals(1, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_EXPIRED]));
119 $this->assertEquals(1, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_CLEANED]));
120
121 // No new records are generated.
122 $numexpired = $expired->flag_expired();
123 $this->assertEquals(0, $numexpired);
124 $this->assertEquals(2, $DB->count_records('tool_dataprivacy_ctxexpired'));
125 $deleted = $expired->delete();
126 $this->assertEquals(0, $deleted);
e60058ff 127
c8e49221
AG
128 // No user data left in mod_assign.
129 $this->assertEquals(0, $DB->count_records('assign_submission'));
130
e60058ff
DM
131 // The user is deleted.
132 $deleteduser = \core_user::get_user($user2->id, 'id, deleted', IGNORE_MISSING);
133 $this->assertEquals(1, $deleteduser->deleted);
5efc1f9e
DM
134 }
135
136 /**
137 * Test expired course and course stuff flagging and deletion.
138 *
139 * @return null
140 */
141 public function test_expired_course_related_contexts() {
142 global $DB;
143
0462786a
JP
144 $purpose1 = api::create_purpose((object)['name' => 'p1', 'retentionperiod' => 'PT1H', 'lawfulbases' => 'gdpr_art_6_1_a']);
145 $purpose2 = api::create_purpose((object)['name' => 'p1', 'retentionperiod' => 'P1000Y', 'lawfulbases' => 'gdpr_art_6_1_b']);
5efc1f9e
DM
146 $cat = api::create_category((object)['name' => 'a']);
147
148 $record = (object)[
149 'purposeid' => $purpose1->get('id'),
150 'categoryid' => $cat->get('id'),
151 'contextlevel' => CONTEXT_SYSTEM,
152 ];
153 api::set_contextlevel($record);
154
155 list($purposevar, $categoryvar) = data_registry::var_names_from_context(
156 \context_helper::get_class_for_level(CONTEXT_COURSE)
157 );
158 set_config($purposevar, $purpose1->get('id'), 'tool_dataprivacy');
159
a8a69050 160 // A lot more time for modules.
5efc1f9e
DM
161 list($purposevar, $categoryvar) = data_registry::var_names_from_context(
162 \context_helper::get_class_for_level(CONTEXT_MODULE)
163 );
164 set_config($purposevar, $purpose2->get('id'), 'tool_dataprivacy');
165
166 $course1 = $this->getDataGenerator()->create_course();
167
168 // Old course.
169 $course2 = $this->getDataGenerator()->create_course(['startdate' => '1', 'enddate' => '2']);
170 $forum1 = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id));
171 $forum2 = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id));
172
173 // We want to override this last module instance purpose so we can test that modules are also
174 // returned as expired.
175 $forum2ctx = \context_module::instance($forum2->cmid);
176 $record = (object)[
177 'purposeid' => $purpose1->get('id'),
178 'categoryid' => $cat->get('id'),
179 'contextid' => $forum2ctx->id,
180 ];
181 api::set_context_instance($record);
182
183 // Ongoing course.
184 $course3 = $this->getDataGenerator()->create_course(['startdate' => '1', 'enddate' => time()]);
185 $forum3 = $this->getDataGenerator()->create_module('forum', array('course' => $course3->id));
186
187 $expired = new \tool_dataprivacy\expired_course_related_contexts();
188 $numexpired = $expired->flag_expired();
189
190 // Only 1 module has expired.
191 $this->assertEquals(1, $numexpired);
192 $this->assertEquals(1, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_EXPIRED]));
193
194 // Add a forum1 override to 1h retention period so both forum1 and course2 are also expired.
195 $forum1ctx = \context_module::instance($forum1->cmid);
196 $record->purposeid = $purpose1->get('id');
197 $record->contextid = $forum1ctx->id;
198 api::set_context_instance($record);
199 $numexpired = $expired->flag_expired();
200 $this->assertEquals(2, $numexpired);
201 $this->assertEquals(3, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_EXPIRED]));
202
203 // Approve forum1 to be deleted.
204 $expiredctx = expired_context::get_record(['contextid' => $forum1ctx->id]);
205 api::set_expired_context_status($expiredctx, expired_context::STATUS_APPROVED);
206
207 // Delete expired contexts.
208 $deleted = $expired->delete();
209 $this->assertEquals(1, $deleted);
210 $this->assertEquals(1, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_CLEANED]));
211
212 $expiredctx = expired_context::get_record(['contextid' => $forum2ctx->id]);
213 api::set_expired_context_status($expiredctx, expired_context::STATUS_APPROVED);
214
215 $course2ctx = \context_course::instance($course2->id);
216 $expiredctx = expired_context::get_record(['contextid' => $course2ctx->id]);
217 api::set_expired_context_status($expiredctx, expired_context::STATUS_APPROVED);
218
219 // Delete expired contexts.
220 $deleted = $expired->delete();
221 $this->assertEquals(2, $deleted);
222 $this->assertEquals(3, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_CLEANED]));
223
224 // No new records are generated.
225 $numexpired = $expired->flag_expired();
226 $this->assertEquals(0, $numexpired);
227 $this->assertEquals(3, $DB->count_records('tool_dataprivacy_ctxexpired'));
228 $deleted = $expired->delete();
229 $this->assertEquals(0, $deleted);
230
231 }
232}