diff --git a/admin/tool/dataprivacy/classes/expired_contexts_manager.php b/admin/tool/dataprivacy/classes/expired_contexts_manager.php index e91601f667b..e71422df3b7 100644 --- a/admin/tool/dataprivacy/classes/expired_contexts_manager.php +++ b/admin/tool/dataprivacy/classes/expired_contexts_manager.php @@ -51,6 +51,13 @@ abstract class expired_contexts_manager { */ abstract protected function get_expired_contexts(); + /** + * Specify with context levels this expired contexts manager is deleting. + * + * @return int[] + */ + abstract protected function get_context_levels(); + /** * Flag expired contexts as expired. * @@ -85,28 +92,16 @@ abstract class expired_contexts_manager { $privacymanager = new \core_privacy\manager(); - $levels = [CONTEXT_USER, CONTEXT_MODULE, CONTEXT_BLOCK, CONTEXT_COURSE]; - foreach ($levels as $level) { + foreach ($this->get_context_levels() as $level) { $expiredcontexts = expired_context::get_records_by_contextlevel($level, expired_context::STATUS_APPROVED); foreach ($expiredcontexts as $expiredctx) { - $context = \context::instance_by_id($expiredctx->get('contextid'), IGNORE_MISSING); - if (!$context) { - api::delete_expired_context($expiredctx->get('contextid')); + if (!$this->delete_expired_context($privacymanager, $expiredctx)) { continue; } - if (!PHPUNIT_TEST) { - mtrace('Deleting context ' . $context->id . ' - ' . - shorten_text($context->get_context_name(true, true))); - } - - $privacymanager->delete_data_for_all_users_in_context($context); - - api::set_expired_context_status($expiredctx, expired_context::STATUS_CLEANED); - $numprocessed += 1; if ($numprocessed == self::DELETE_LIMIT) { // Close the recordset. @@ -119,6 +114,32 @@ abstract class expired_contexts_manager { return $numprocessed; } + /** + * Deletes user data from the provided context. + * + * @param \core_privacy\manager $privacymanager + * @param \tool_dataprivacy\expired_context $expiredctx + * @return \context|false + */ + protected function delete_expired_context(\core_privacy\manager $privacymanager, \tool_dataprivacy\expired_context $expiredctx) { + + $context = \context::instance_by_id($expiredctx->get('contextid'), IGNORE_MISSING); + if (!$context) { + api::delete_expired_context($expiredctx->get('contextid')); + return false; + } + + if (!PHPUNIT_TEST) { + mtrace('Deleting context ' . $context->id . ' - ' . + shorten_text($context->get_context_name(true, true))); + } + + $privacymanager->delete_data_for_all_users_in_context($context); + api::set_expired_context_status($expiredctx, expired_context::STATUS_CLEANED); + + return $context; + } + /** * Check that the requirements to start deleting contexts are satisified. * diff --git a/admin/tool/dataprivacy/classes/expired_course_related_contexts.php b/admin/tool/dataprivacy/classes/expired_course_related_contexts.php index 24fc5b22c15..f878edff093 100644 --- a/admin/tool/dataprivacy/classes/expired_course_related_contexts.php +++ b/admin/tool/dataprivacy/classes/expired_course_related_contexts.php @@ -35,6 +35,15 @@ defined('MOODLE_INTERNAL') || die(); */ class expired_course_related_contexts extends \tool_dataprivacy\expired_contexts_manager { + /** + * Course-related context levels. + * + * @return int[] + */ + protected function get_context_levels() { + return [CONTEXT_MODULE, CONTEXT_BLOCK, CONTEXT_COURSE]; + } + /** * Returns a recordset with user context instances that are possibly expired (to be confirmed by get_recordset_callback). * diff --git a/admin/tool/dataprivacy/classes/expired_user_contexts.php b/admin/tool/dataprivacy/classes/expired_user_contexts.php index a29fc5dd7c6..62d9485e47d 100644 --- a/admin/tool/dataprivacy/classes/expired_user_contexts.php +++ b/admin/tool/dataprivacy/classes/expired_user_contexts.php @@ -36,6 +36,15 @@ defined('MOODLE_INTERNAL') || die(); */ class expired_user_contexts extends \tool_dataprivacy\expired_contexts_manager { + /** + * Only user level. + * + * @return int[] + */ + protected function get_context_levels() { + return [CONTEXT_USER]; + } + /** * Returns the user context instances that are expired. * @@ -95,4 +104,25 @@ class expired_user_contexts extends \tool_dataprivacy\expired_contexts_manager { return $expiredcontexts; } + + /** + * Deletes user data from the provided context. + * + * Overwritten to delete the user. + * + * @param \core_privacy\manager $privacymanager + * @param \tool_dataprivacy\expired_context $expiredctx + * @return \context|false + */ + protected function delete_expired_context(\core_privacy\manager $privacymanager, \tool_dataprivacy\expired_context $expiredctx) { + if (!$context = parent::delete_expired_context($privacymanager, $expiredctx)) { + return false; + } + + // Delete the user. + $user = \core_user::get_user($context->instanceid, '*', MUST_EXIST); + delete_user($user); + + return $context; + } } diff --git a/admin/tool/dataprivacy/classes/task/process_data_request_task.php b/admin/tool/dataprivacy/classes/task/process_data_request_task.php index b0615c602dd..9a471d6bd70 100644 --- a/admin/tool/dataprivacy/classes/task/process_data_request_task.php +++ b/admin/tool/dataprivacy/classes/task/process_data_request_task.php @@ -199,5 +199,10 @@ class process_data_request_task extends adhoc_task { } mtrace('Message sent to requester: ' . $messagetextdata['username']); } + + if ($request->type == api::DATAREQUEST_TYPE_DELETE) { + // Delete the user. + delete_user($foruser); + } } } diff --git a/admin/tool/dataprivacy/tests/expired_contexts_test.php b/admin/tool/dataprivacy/tests/expired_contexts_test.php index 2f1f1b66f12..6aa16a645f9 100644 --- a/admin/tool/dataprivacy/tests/expired_contexts_test.php +++ b/admin/tool/dataprivacy/tests/expired_contexts_test.php @@ -77,7 +77,7 @@ class tool_dataprivacy_expired_contexts_testcase extends advanced_testcase { // Old course. $course2 = $this->getDataGenerator()->create_course(['startdate' => '1', 'enddate' => '2']); // Ongoing course. - $course3 = $this->getDataGenerator()->create_course(['startdate' => '1', 'enddate' => time()]); + $course3 = $this->getDataGenerator()->create_course(['startdate' => '1', 'enddate' => time() + YEARSECS]); $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student'); $this->getDataGenerator()->enrol_user($user2->id, $course2->id, 'student'); @@ -90,7 +90,7 @@ class tool_dataprivacy_expired_contexts_testcase extends advanced_testcase { $this->assertEquals(2, $numexpired); $this->assertEquals(2, $DB->count_records('tool_dataprivacy_ctxexpired', ['status' => expired_context::STATUS_EXPIRED])); - // Approve user1 to be deleted. + // Approve user2 to be deleted. $user2ctx = \context_user::instance($user2->id); $expiredctx = expired_context::get_record(['contextid' => $user2ctx->id]); api::set_expired_context_status($expiredctx, expired_context::STATUS_APPROVED); @@ -108,6 +108,10 @@ class tool_dataprivacy_expired_contexts_testcase extends advanced_testcase { $this->assertEquals(2, $DB->count_records('tool_dataprivacy_ctxexpired')); $deleted = $expired->delete(); $this->assertEquals(0, $deleted); + + // The user is deleted. + $deleteduser = \core_user::get_user($user2->id, 'id, deleted', IGNORE_MISSING); + $this->assertEquals(1, $deleteduser->deleted); } /**