MDL-62904 tool_dataprivacy: Add data request links in profile page
[moodle.git] / admin / tool / dataprivacy / lib.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 * Data privacy plugin library
19 * @package tool_dataprivacy
20 * @copyright 2018 onwards Jun Pataleta
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 */
23
24use core_user\output\myprofile\tree;
25
26defined('MOODLE_INTERNAL') || die();
27
28/**
29 * Add nodes to myprofile page.
30 *
31 * @param tree $tree Tree object
32 * @param stdClass $user User object
33 * @param bool $iscurrentuser
34 * @param stdClass $course Course object
35 * @return bool
36 * @throws coding_exception
37 * @throws dml_exception
38 * @throws moodle_exception
39 */
40function tool_dataprivacy_myprofile_navigation(tree $tree, $user, $iscurrentuser, $course) {
41 global $PAGE, $USER;
42
43 // Get the Privacy and policies category.
44 if (!array_key_exists('privacyandpolicies', $tree->__get('categories'))) {
45 // Create the category.
46 $categoryname = get_string('privacyandpolicies', 'admin');
47 $category = new core_user\output\myprofile\category('privacyandpolicies', $categoryname, 'contact');
48 $tree->add_category($category);
49 } else {
50 // Get the existing category.
51 $category = $tree->__get('categories')['privacyandpolicies'];
52 }
53
54 // Contact data protection officer link.
55 if (\tool_dataprivacy\api::can_contact_dpo() && $iscurrentuser) {
56 $renderer = $PAGE->get_renderer('tool_dataprivacy');
57 $content = $renderer->render_contact_dpo_link($USER->email);
58 $node = new core_user\output\myprofile\node('privacyandpolicies', 'contactdpo', null, null, null, $content);
59 $category->add_node($node);
60 $PAGE->requires->js_call_amd('tool_dataprivacy/myrequestactions', 'init');
61
62 $url = new moodle_url('/admin/tool/dataprivacy/mydatarequests.php');
63 $node = new core_user\output\myprofile\node('privacyandpolicies', 'datarequests',
64 get_string('datarequests', 'tool_dataprivacy'), null, $url);
65 $category->add_node($node);
500dc0b1
JP
66
67 // Check if the user has an ongoing data export request.
68 $hasexportrequest = \tool_dataprivacy\api::has_ongoing_request($user->id, \tool_dataprivacy\api::DATAREQUEST_TYPE_EXPORT);
69 // Show data export link only if the user doesn't have an ongoing data export request.
70 if (!$hasexportrequest) {
71 $exportparams = ['type' => \tool_dataprivacy\api::DATAREQUEST_TYPE_EXPORT];
72 $exporturl = new moodle_url('/admin/tool/dataprivacy/createdatarequest.php', $exportparams);
73 $exportnode = new core_user\output\myprofile\node('privacyandpolicies', 'requestdataexport',
74 get_string('requesttypeexport', 'tool_dataprivacy'), null, $exporturl);
75 $category->add_node($exportnode);
76 }
77
78 // Check if the user has an ongoing data deletion request.
79 $hasdeleterequest = \tool_dataprivacy\api::has_ongoing_request($user->id, \tool_dataprivacy\api::DATAREQUEST_TYPE_DELETE);
80 // Show data deletion link only if the user doesn't have an ongoing data deletion request.
81 if (!$hasdeleterequest) {
82 $deleteparams = ['type' => \tool_dataprivacy\api::DATAREQUEST_TYPE_DELETE];
83 $deleteurl = new moodle_url('/admin/tool/dataprivacy/createdatarequest.php', $deleteparams);
84 $deletenode = new core_user\output\myprofile\node('privacyandpolicies', 'requestdatadeletion',
85 get_string('deletemyaccount', 'tool_dataprivacy'), null, $deleteurl);
86 $category->add_node($deletenode);
87 }
5efc1f9e
DM
88 }
89
edbdeb63
AG
90 $summaryurl = new moodle_url('/admin/tool/dataprivacy/summary.php');
91 $summarynode = new core_user\output\myprofile\node('privacyandpolicies', 'retentionsummary',
92 get_string('dataretentionsummary', 'tool_dataprivacy'), null, $summaryurl);
93 $category->add_node($summarynode);
94
5efc1f9e
DM
95 // Add the Privacy category to the tree if it's not empty and it doesn't exist.
96 $nodes = $category->nodes;
97 if (!empty($nodes)) {
98 if (!array_key_exists('privacyandpolicies', $tree->__get('categories'))) {
99 $tree->add_category($category);
100 }
101 return true;
102 }
103
104 return false;
105}
106
edbdeb63
AG
107/**
108 * Callback to add footer elements.
109 *
110 * @return string HTML footer content
111 */
112function tool_dataprivacy_standard_footer_html() {
113
114 $url = new moodle_url('/admin/tool/dataprivacy/summary.php');
115 $output = html_writer::link($url, get_string('dataretentionsummary', 'tool_dataprivacy'));
116 $output = html_writer::div($output, 'summaryfooter');
117
118 return $output;
119}
120
5efc1f9e
DM
121/**
122 * Fragment to add a new purpose.
123 *
124 * @param array $args The fragment arguments.
125 * @return string The rendered mform fragment.
126 */
127function tool_dataprivacy_output_fragment_addpurpose_form($args) {
128
129 $formdata = [];
130 if (!empty($args['jsonformdata'])) {
131 $serialiseddata = json_decode($args['jsonformdata']);
132 parse_str($serialiseddata, $formdata);
133 }
134
135 $persistent = new \tool_dataprivacy\purpose();
136 $mform = new \tool_dataprivacy\form\purpose(null, ['persistent' => $persistent],
137 'post', '', null, true, $formdata);
138
139 if (!empty($args['jsonformdata'])) {
140 // Show errors if data was received.
141 $mform->is_validated();
142 }
143
144 return $mform->render();
145}
146
147/**
148 * Fragment to add a new category.
149 *
150 * @param array $args The fragment arguments.
151 * @return string The rendered mform fragment.
152 */
153function tool_dataprivacy_output_fragment_addcategory_form($args) {
154
155 $formdata = [];
156 if (!empty($args['jsonformdata'])) {
157 $serialiseddata = json_decode($args['jsonformdata']);
158 parse_str($serialiseddata, $formdata);
159 }
160
161 $persistent = new \tool_dataprivacy\category();
162 $mform = new \tool_dataprivacy\form\category(null, ['persistent' => $persistent],
163 'post', '', null, true, $formdata);
164
165 if (!empty($args['jsonformdata'])) {
166 // Show errors if data was received.
167 $mform->is_validated();
168 }
169
170 return $mform->render();
171}
172
173/**
174 * Fragment to edit a context purpose and category.
175 *
176 * @param array $args The fragment arguments.
177 * @return string The rendered mform fragment.
178 */
179function tool_dataprivacy_output_fragment_context_form($args) {
180 global $PAGE;
181
182 $contextid = $args[0];
183
184 $context = \context_helper::instance_by_id($contextid);
185 $customdata = \tool_dataprivacy\form\context_instance::get_context_instance_customdata($context);
186
187 if (!empty($customdata['purposeretentionperiods'])) {
a8a69050
DM
188 $PAGE->requires->js_call_amd('tool_dataprivacy/effective_retention_period', 'init',
189 [$customdata['purposeretentionperiods']]);
5efc1f9e
DM
190 }
191 $mform = new \tool_dataprivacy\form\context_instance(null, $customdata);
192 return $mform->render();
193}
194
195/**
196 * Fragment to edit a contextlevel purpose and category.
197 *
198 * @param array $args The fragment arguments.
199 * @return string The rendered mform fragment.
200 */
201function tool_dataprivacy_output_fragment_contextlevel_form($args) {
202 global $PAGE;
203
204 $contextlevel = $args[0];
205 $customdata = \tool_dataprivacy\form\contextlevel::get_contextlevel_customdata($contextlevel);
206
207 if (!empty($customdata['purposeretentionperiods'])) {
a8a69050
DM
208 $PAGE->requires->js_call_amd('tool_dataprivacy/effective_retention_period', 'init',
209 [$customdata['purposeretentionperiods']]);
5efc1f9e
DM
210 }
211
212 $mform = new \tool_dataprivacy\form\contextlevel(null, $customdata);
213 return $mform->render();
214}
215
216/**
217 * Serves any files associated with the data privacy settings.
218 *
219 * @param stdClass $course Course object
220 * @param stdClass $cm Course module object
221 * @param context $context Context
222 * @param string $filearea File area for data privacy
223 * @param array $args Arguments
224 * @param bool $forcedownload If we are forcing the download
225 * @param array $options More options
226 * @return bool Returns false if we don't find a file.
227 */
228function tool_dataprivacy_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
229 if ($context->contextlevel == CONTEXT_USER) {
cb775057
JP
230 // Make sure the user is logged in.
231 require_login(null, false);
232
635c7b29 233 // Get the data request ID. This should be the first element of the $args array.
234 $itemid = $args[0];
235 // Fetch the data request object. An invalid ID will throw an exception.
236 $datarequest = new \tool_dataprivacy\data_request($itemid);
237
238 // Check if user is allowed to download it.
239 if (!\tool_dataprivacy\api::can_download_data_request_for_user($context->instanceid, $datarequest->get('requestedby'))) {
240 return false;
cb775057
JP
241 }
242
693f690c
MH
243 // Make the file unavailable if it has expired.
244 if (\tool_dataprivacy\data_request::is_expired($datarequest)) {
245 send_file_not_found();
246 }
247
cb775057 248 // All good. Serve the exported data.
5efc1f9e
DM
249 $fs = get_file_storage();
250 $relativepath = implode('/', $args);
251 $fullpath = "/$context->id/tool_dataprivacy/$filearea/$relativepath";
252 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
253 return false;
254 }
255 send_stored_file($file, 0, 0, $forcedownload, $options);
256 } else {
257 send_file_not_found();
258 }
259}