PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/admin/tool/dataprivacy/lib.php

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