MDL-56595 tool_usertours: set page params when configuring tours/steps.
[moodle.git] / admin / tool / dataprivacy / lib.php
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/>.
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  */
24 use core_user\output\myprofile\tree;
26 defined('MOODLE_INTERNAL') || die();
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  */
40 function tool_dataprivacy_myprofile_navigation(tree $tree, $user, $iscurrentuser, $course) {
41     global $PAGE, $USER;
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     }
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');
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);
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         }
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 and has permission
81         // to create data deletion request.
82         if (!$hasdeleterequest && \tool_dataprivacy\api::can_create_data_deletion_request_for_self()) {
83             $deleteparams = ['type' => \tool_dataprivacy\api::DATAREQUEST_TYPE_DELETE];
84             $deleteurl = new moodle_url('/admin/tool/dataprivacy/createdatarequest.php', $deleteparams);
85             $deletenode = new core_user\output\myprofile\node('privacyandpolicies', 'requestdatadeletion',
86                 get_string('deletemyaccount', 'tool_dataprivacy'), null, $deleteurl);
87             $category->add_node($deletenode);
88         }
89     }
91     // A returned 0 means that the setting was set and disabled, false means that there is no value for the provided setting.
92     $showsummary = get_config('tool_dataprivacy', 'showdataretentionsummary');
93     if ($showsummary === false) {
94         // This means that no value is stored in db. We use the default value in this case.
95         $showsummary = true;
96     }
98     if ($showsummary && $iscurrentuser) {
99         $summaryurl = new moodle_url('/admin/tool/dataprivacy/summary.php');
100         $summarynode = new core_user\output\myprofile\node('privacyandpolicies', 'retentionsummary',
101             get_string('dataretentionsummary', 'tool_dataprivacy'), null, $summaryurl);
102         $category->add_node($summarynode);
103     }
105     // Add the Privacy category to the tree if it's not empty and it doesn't exist.
106     $nodes = $category->nodes;
107     if (!empty($nodes)) {
108         if (!array_key_exists('privacyandpolicies', $tree->__get('categories'))) {
109             $tree->add_category($category);
110         }
111         return true;
112     }
114     return false;
117 /**
118  * Callback to add footer elements.
119  *
120  * @return string HTML footer content
121  */
122 function tool_dataprivacy_standard_footer_html() {
123     $output = '';
125     // A returned 0 means that the setting was set and disabled, false means that there is no value for the provided setting.
126     $showsummary = get_config('tool_dataprivacy', 'showdataretentionsummary');
127     if ($showsummary === false) {
128         // This means that no value is stored in db. We use the default value in this case.
129         $showsummary = true;
130     }
132     if ($showsummary) {
133         $url = new moodle_url('/admin/tool/dataprivacy/summary.php');
134         $output = html_writer::link($url, get_string('dataretentionsummary', 'tool_dataprivacy'));
135         $output = html_writer::div($output, 'tool_dataprivacy');
136     }
137     return $output;
140 /**
141  * Fragment to add a new purpose.
142  *
143  * @param array $args The fragment arguments.
144  * @return string The rendered mform fragment.
145  */
146 function tool_dataprivacy_output_fragment_addpurpose_form($args) {
148     $formdata = [];
149     if (!empty($args['jsonformdata'])) {
150         $serialiseddata = json_decode($args['jsonformdata']);
151         parse_str($serialiseddata, $formdata);
152     }
154     $persistent = new \tool_dataprivacy\purpose();
155     $mform = new \tool_dataprivacy\form\purpose(null, ['persistent' => $persistent],
156         'post', '', null, true, $formdata);
158     if (!empty($args['jsonformdata'])) {
159         // Show errors if data was received.
160         $mform->is_validated();
161     }
163     return $mform->render();
166 /**
167  * Fragment to add a new category.
168  *
169  * @param array $args The fragment arguments.
170  * @return string The rendered mform fragment.
171  */
172 function tool_dataprivacy_output_fragment_addcategory_form($args) {
174     $formdata = [];
175     if (!empty($args['jsonformdata'])) {
176         $serialiseddata = json_decode($args['jsonformdata']);
177         parse_str($serialiseddata, $formdata);
178     }
180     $persistent = new \tool_dataprivacy\category();
181     $mform = new \tool_dataprivacy\form\category(null, ['persistent' => $persistent],
182         'post', '', null, true, $formdata);
184     if (!empty($args['jsonformdata'])) {
185         // Show errors if data was received.
186         $mform->is_validated();
187     }
189     return $mform->render();
192 /**
193  * Fragment to edit a context purpose and category.
194  *
195  * @param array $args The fragment arguments.
196  * @return string The rendered mform fragment.
197  */
198 function tool_dataprivacy_output_fragment_context_form($args) {
199     global $PAGE;
201     $contextid = $args[0];
203     $context = \context_helper::instance_by_id($contextid);
204     $customdata = \tool_dataprivacy\form\context_instance::get_context_instance_customdata($context);
206     if (!empty($customdata['purposeretentionperiods'])) {
207         $PAGE->requires->js_call_amd('tool_dataprivacy/effective_retention_period', 'init',
208             [$customdata['purposeretentionperiods']]);
209     }
210     $mform = new \tool_dataprivacy\form\context_instance(null, $customdata);
211     return $mform->render();
214 /**
215  * Fragment to edit a contextlevel purpose and category.
216  *
217  * @param array $args The fragment arguments.
218  * @return string The rendered mform fragment.
219  */
220 function tool_dataprivacy_output_fragment_contextlevel_form($args) {
221     global $PAGE;
223     $contextlevel = $args[0];
224     $customdata = \tool_dataprivacy\form\contextlevel::get_contextlevel_customdata($contextlevel);
226     if (!empty($customdata['purposeretentionperiods'])) {
227         $PAGE->requires->js_call_amd('tool_dataprivacy/effective_retention_period', 'init',
228             [$customdata['purposeretentionperiods']]);
229     }
231     $mform = new \tool_dataprivacy\form\contextlevel(null, $customdata);
232     return $mform->render();
235 /**
236  * Serves any files associated with the data privacy settings.
237  *
238  * @param stdClass $course Course object
239  * @param stdClass $cm Course module object
240  * @param context $context Context
241  * @param string $filearea File area for data privacy
242  * @param array $args Arguments
243  * @param bool $forcedownload If we are forcing the download
244  * @param array $options More options
245  * @return bool Returns false if we don't find a file.
246  */
247 function tool_dataprivacy_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
248     if ($context->contextlevel == CONTEXT_USER) {
249         // Make sure the user is logged in.
250         require_login(null, false);
252         // Get the data request ID. This should be the first element of the $args array.
253         $itemid = $args[0];
254         // Fetch the data request object. An invalid ID will throw an exception.
255         $datarequest = new \tool_dataprivacy\data_request($itemid);
257         // Check if user is allowed to download it.
258         if (!\tool_dataprivacy\api::can_download_data_request_for_user($context->instanceid, $datarequest->get('requestedby'))) {
259             return false;
260         }
262         // Make the file unavailable if it has expired.
263         if (\tool_dataprivacy\data_request::is_expired($datarequest)) {
264             send_file_not_found();
265         }
267         // All good. Serve the exported data.
268         $fs = get_file_storage();
269         $relativepath = implode('/', $args);
270         $fullpath = "/$context->id/tool_dataprivacy/$filearea/$relativepath";
271         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
272             return false;
273         }
274         send_stored_file($file, 0, 0, $forcedownload, $options);
275     } else {
276         send_file_not_found();
277     }