personal_data.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CoreBundle\Entity\Repository\LegalRepository;
  4. /**
  5. * @package chamilo.messages
  6. */
  7. $cidReset = true;
  8. require_once __DIR__.'/../inc/global.inc.php';
  9. api_set_more_memory_and_time_limits();
  10. api_block_anonymous_users();
  11. if (api_get_configuration_value('disable_gdpr')) {
  12. api_not_allowed(true);
  13. }
  14. $userId = api_get_user_id();
  15. $userInfo = api_get_user_info($userId);
  16. if (empty($userInfo)) {
  17. api_not_allowed(true);
  18. }
  19. $substitutionTerms = [
  20. 'password' => get_lang('Encrypted data'),
  21. 'salt' => get_lang('Random data'),
  22. 'empty' => get_lang('No data available'),
  23. ];
  24. $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
  25. $formToString = '';
  26. if (api_get_setting('allow_terms_conditions') === 'true') {
  27. $form = new FormValidator('delete_term', 'post', api_get_self().'?action=delete_legal&user_id='.$userId);
  28. $form->addHtml(Display::return_message(get_lang('You can ask below for your legal agreement to be deleted or your account to be deleted.</br>In the case of the legal agreement, once deleted you will have to accept it again on your next login to be able to access the platform and recover your access, because we cannot reasonably at the same time give you a personal environment and not treat your personal data.</br>In the case of an account deletion, your account will be deleted along with all of your course subscriptions and all the information related to your account. Please select the corresponding option with care. In both cases, one of our administrators will review your request before it is effective, to avoid any misunderstanding and definitive loss of your data.'), 'normal', false));
  29. $form->addTextarea('explanation', [get_lang('Delete legal agreement'), get_lang('ExplanationDelete legal agreement')], [], true);
  30. $form->addHidden('action', 'delete_legal');
  31. $form->addButtonSave(get_lang('Delete legal agreement'));
  32. $formToString = $form->returnForm();
  33. $formDelete = new FormValidator('delete_account', 'post', api_get_self().'?action=delete_account&user_id='.$userId);
  34. $formDelete->addTextarea(
  35. 'explanation',
  36. [get_lang('Delete account'), get_lang('ExplanationDelete account')],
  37. [],
  38. true
  39. );
  40. $formDelete->addHidden('action', 'delete_account');
  41. $formDelete->addButtonDelete(get_lang('Delete account'));
  42. $formToString .= $formDelete->returnForm();
  43. }
  44. switch ($action) {
  45. case 'send_legal':
  46. $language = api_get_interface_language();
  47. $language = api_get_language_id($language);
  48. $terms = LegalManager::get_last_condition($language);
  49. if (!$terms) {
  50. //look for the default language
  51. $language = api_get_setting('platformLanguage');
  52. $language = api_get_language_id($language);
  53. $terms = LegalManager::get_last_condition($language);
  54. }
  55. $legalAcceptType = $terms['version'].':'.$terms['language_id'].':'.time();
  56. UserManager::update_extra_field_value(
  57. $userId,
  58. 'legal_accept',
  59. $legalAcceptType
  60. );
  61. Event::addEvent(
  62. LOG_TERM_CONDITION_ACCEPTED,
  63. LOG_USER_OBJECT,
  64. api_get_user_info($userId),
  65. api_get_utc_datetime()
  66. );
  67. $bossList = UserManager::getStudentBossList($userId);
  68. if (!empty($bossList)) {
  69. $bossList = array_column($bossList, 'boss_id');
  70. $currentUserInfo = api_get_user_info($userId);
  71. foreach ($bossList as $bossId) {
  72. $subjectEmail = sprintf(
  73. get_lang('User %s signed the agreement.'),
  74. $currentUserInfo['complete_name']
  75. );
  76. $contentEmail = sprintf(
  77. get_lang('User %s signed the agreement.TheDateY'),
  78. $currentUserInfo['complete_name'],
  79. api_get_local_time($time)
  80. );
  81. MessageManager::send_message_simple(
  82. $bossId,
  83. $subjectEmail,
  84. $contentEmail,
  85. $user_id
  86. );
  87. }
  88. }
  89. Display::addFlash(Display::return_message(get_lang('Saved..')));
  90. header('Location: '.api_get_self());
  91. exit;
  92. break;
  93. case 'delete_account':
  94. if ($formDelete->validate()) {
  95. $explanation = $formDelete->getSubmitValue('explanation');
  96. UserManager::createDataPrivacyExtraFields();
  97. UserManager::update_extra_field_value(
  98. $userId,
  99. 'request_for_delete_account',
  100. 1
  101. );
  102. UserManager::update_extra_field_value(
  103. $userId,
  104. 'request_for_delete_account_justification',
  105. $explanation
  106. );
  107. Display::addFlash(Display::return_message(get_lang('Saved..')));
  108. Event::addEvent(
  109. LOG_USER_DELETE_ACCOUNT_REQUEST,
  110. LOG_USER_OBJECT,
  111. $userInfo
  112. );
  113. $url = api_get_path(WEB_CODE_PATH).'admin/user_list_consent.php';
  114. $link = Display::url($url, $url);
  115. $subject = get_lang('Request for account removal');
  116. $content = sprintf(
  117. get_lang('User %s asked for the deletion of his/her account, explaining that "%s". You can process the request here: %s'),
  118. $userInfo['complete_name'],
  119. $explanation,
  120. $link
  121. );
  122. $email = api_get_configuration_value('data_protection_officer_email');
  123. if (!empty($email)) {
  124. api_mail_html('', $email, $subject, $content);
  125. } else {
  126. MessageManager::sendMessageToAllAdminUsers(api_get_user_id(), $subject, $content);
  127. }
  128. header('Location: '.api_get_self());
  129. exit;
  130. }
  131. break;
  132. case 'delete_legal':
  133. if ($form->validate()) {
  134. $explanation = $form->getSubmitValue('explanation');
  135. UserManager::createDataPrivacyExtraFields();
  136. UserManager::update_extra_field_value(
  137. $userId,
  138. 'request_for_legal_agreement_consent_removal',
  139. 1
  140. );
  141. UserManager::update_extra_field_value(
  142. $userId,
  143. 'request_for_legal_agreement_consent_removal_justification',
  144. $explanation
  145. );
  146. Display::addFlash(Display::return_message(get_lang('Sent')));
  147. Event::addEvent(
  148. LOG_USER_REMOVED_LEGAL_ACCEPT,
  149. LOG_USER_OBJECT,
  150. $userInfo
  151. );
  152. $url = api_get_path(WEB_CODE_PATH).'admin/user_list_consent.php';
  153. $link = Display::url($url, $url);
  154. $subject = get_lang('Request for consent withdrawal on legal terms');
  155. $content = sprintf(
  156. get_lang('User %s asked for the removal of his/her consent to our legal terms, explaining that "%s". You can process the request here: %s'),
  157. $userInfo['complete_name'],
  158. $explanation,
  159. $link
  160. );
  161. $email = api_get_configuration_value('data_protection_officer_email');
  162. if (!empty($email)) {
  163. api_mail_html('', $email, $subject, $content);
  164. } else {
  165. MessageManager::sendMessageToAllAdminUsers(api_get_user_id(), $subject, $content);
  166. }
  167. header('Location: '.api_get_self());
  168. exit;
  169. }
  170. break;
  171. }
  172. $propertiesToJson = UserManager::getRepository()->getPersonalDataToJson($userId, $substitutionTerms);
  173. if (!empty($_GET['export'])) {
  174. $filename = md5(mt_rand(0, 1000000)).'.json';
  175. $path = api_get_path(SYS_ARCHIVE_PATH).$filename;
  176. $writeResult = file_put_contents($path, $propertiesToJson);
  177. if ($writeResult !== false) {
  178. DocumentManager::file_send_for_download($path, true, $filename);
  179. exit;
  180. }
  181. }
  182. $allowSocial = api_get_setting('allow_social_tool') === 'true';
  183. $nameTools = get_lang('Personal data');
  184. $show_message = null;
  185. if ($allowSocial) {
  186. $this_section = SECTION_SOCIAL;
  187. $interbreadcrumb[] = [
  188. 'url' => api_get_path(WEB_PATH).'main/social/home.php',
  189. 'name' => get_lang('Social network'),
  190. ];
  191. } else {
  192. $this_section = SECTION_MYPROFILE;
  193. $interbreadcrumb[] = [
  194. 'url' => api_get_path(WEB_PATH).'main/auth/profile.php',
  195. 'name' => get_lang('Profile'),
  196. ];
  197. }
  198. $interbreadcrumb[] = ['url' => '#', 'name' => get_lang('Personal data')];
  199. // LEFT CONTENT
  200. $socialMenuBlock = '';
  201. if ($allowSocial) {
  202. // Block Social Menu
  203. $socialMenuBlock = SocialManager::show_social_menu('personal-data');
  204. }
  205. // MAIN CONTENT
  206. $personalDataContent = '<ul>';
  207. $properties = json_decode($propertiesToJson);
  208. $webCoursePath = api_get_path(WEB_COURSE_PATH);
  209. $showWarningMessage = false;
  210. foreach ($properties as $key => $value) {
  211. if (is_array($value) || is_object($value)) {
  212. switch ($key) {
  213. case 'classes':
  214. foreach ($value as $category => $subValue) {
  215. $categoryName = 'Social group';
  216. if ($category == 0) {
  217. $categoryName = 'Class';
  218. }
  219. $personalDataContent .= '<li class="advanced_options" id="personal-data-list-'.$category.'">';
  220. $personalDataContent .= '<u>'.$categoryName.'</u> &gt;</li>';
  221. $personalDataContent .= '<ul id="personal-data-list-'.$category.'_options" style="display:none;">';
  222. if (empty($subValue)) {
  223. $personalDataContent .= '<li>'.get_lang('No data available').'</li>';
  224. } else {
  225. foreach ($subValue as $subSubValue) {
  226. $personalDataContent .= '<li>'.Security::remove_XSS($subSubValue).'</li>';
  227. }
  228. }
  229. $personalDataContent .= '</ul>';
  230. }
  231. break;
  232. case 'extraFields':
  233. $personalDataContent .= '<li>'.$key.': </li><ul>';
  234. if (empty($value)) {
  235. $personalDataContent .= '<li>'.get_lang('No data available').'</li>';
  236. } else {
  237. foreach ($value as $subValue) {
  238. if (is_array($subValue->value)) {
  239. // tags fields can be stored as arrays
  240. $val = json_encode(Security::remove_XSS($subValue->value));
  241. } else {
  242. $val = Security::remove_XSS($subValue->value);
  243. }
  244. $personalDataContent .= '<li>'.$subValue->variable.': '.$val.'</li>';
  245. }
  246. }
  247. $personalDataContent .= '</ul>';
  248. break;
  249. case 'dropBoxSentFiles':
  250. foreach ($value as $category => $subValue) {
  251. $personalDataContent .= '<li class="advanced_options" id="personal-data-list-'.$category.'">';
  252. $personalDataContent .= '<u>'.get_lang($category).'</u> &gt;</li>';
  253. $personalDataContent .= '<ul id="personal-data-list-'.$category.'_options" style="display:none;">';
  254. if (empty($subValue)) {
  255. $personalDataContent .= '<li>'.get_lang('No data available').'</li>';
  256. } else {
  257. if (count($subValue) === 1000) {
  258. $showWarningMessage = true;
  259. }
  260. foreach ($subValue as $subSubValue) {
  261. if ($category === 'DocumentsAdded') {
  262. $documentLink = Display::url(
  263. $subSubValue->code_path,
  264. $webCoursePath.$subSubValue->directory.'/document'.$subSubValue->path
  265. );
  266. $personalDataContent .= '<li>'.$documentLink.'</li>';
  267. } else {
  268. $personalDataContent .= '<li>'.Security::remove_XSS($subSubValue).'</li>';
  269. }
  270. }
  271. }
  272. $personalDataContent .= '</ul>';
  273. }
  274. break;
  275. case 'portals':
  276. case 'roles':
  277. case 'achievedSkills':
  278. case 'sessionAsGeneralCoach':
  279. case 'courses':
  280. case 'groupNames':
  281. case 'groups':
  282. $personalDataContent .= '<li>'.$key.': </li><ul>';
  283. if (empty($subValue)) {
  284. $personalDataContent .= '<li>'.get_lang('No data available').'</li>';
  285. } else {
  286. foreach ($value as $subValue) {
  287. $personalDataContent .= '<li>'.Security::remove_XSS($subValue).'</li>';
  288. }
  289. }
  290. $personalDataContent .= '</ul>';
  291. break;
  292. case 'sessionCourseSubscriptions':
  293. $personalDataContent .= '<li>'.$key.': </li><ul>';
  294. foreach ($value as $session => $courseList) {
  295. $personalDataContent .= '<li>'.$session.'<ul>';
  296. if (empty($courseList)) {
  297. $personalDataContent .= '<li>'.get_lang('No data available').'</li>';
  298. } else {
  299. foreach ($courseList as $course) {
  300. $personalDataContent .= '<li>'.$course.'</li>';
  301. }
  302. }
  303. $personalDataContent .= '</ul>';
  304. }
  305. $personalDataContent .= '</ul>';
  306. break;
  307. default:
  308. //var_dump($key);
  309. break;
  310. }
  311. /*foreach ($value as $subValue) {
  312. foreach ($subValue as $subSubValue) {
  313. var_dump($subSubValue);
  314. //$personalDataContent .= '<li>'.$subSubValue.'</li>';
  315. }
  316. }*/
  317. //skip in some cases
  318. /*sif (!empty($value['date'])) {
  319. $personalDataContent .= '<li>'.$key.': '.$value['date'].'</li>';
  320. } else {
  321. $personalDataContent .= '<li>'.$key.': '.get_lang('Complex data (not shown)').'</li>';
  322. }*/
  323. } else {
  324. $personalDataContent .= '<li>'.$key.': '.Security::remove_XSS($value).'</li>';
  325. }
  326. }
  327. $personalDataContent .= '</ul>';
  328. // Check terms acceptation
  329. $permissionBlock = '';
  330. if (api_get_setting('allow_terms_conditions') === 'true') {
  331. $extraFieldValue = new ExtraFieldValue('user');
  332. $value = $extraFieldValue->get_values_by_handler_and_field_variable(
  333. $userId,
  334. 'legal_accept'
  335. );
  336. $permissionBlock .= Display::return_icon('accept_na.png', get_lang('Rejected'));
  337. if (isset($value['value']) && !empty($value['value'])) {
  338. list($legalId, $legalLanguageId, $legalTime) = explode(':', $value['value']);
  339. $permissionBlock = '<h4>'.get_lang('Current status').'</h4>'.
  340. get_lang('Legal agreement accepted').' '.Display::return_icon('accept.png', get_lang('Legal agreement accepted'), [], ICON_SIZE_TINY).
  341. '<br />';
  342. $permissionBlock .= get_lang('Date').': '.api_get_local_time($legalTime).'<br /><br />';
  343. $permissionBlock .= $formToString;
  344. /*$permissionBlock .= Display::url(
  345. get_lang('Delete legal agreement'),
  346. api_get_self().'?action=delete_legal&user_id='.$userId,
  347. ['class' => 'btn btn-danger btn-xs']
  348. );*/
  349. } else {
  350. // @TODO add action handling for button
  351. $permissionBlock .= Display::url(
  352. get_lang('Send legal agreement'),
  353. api_get_self().'?action=send_legal&user_id='.$userId,
  354. ['class' => 'btn btn-primary btn-xs']
  355. );
  356. }
  357. } else {
  358. $permissionBlock .= get_lang('No terms and conditions available');
  359. }
  360. //Build the final array to pass to template
  361. $personalData = [];
  362. $personalData['data'] = $personalDataContent;
  363. //$personalData['responsible'] = api_get_setting('personal_data_responsible_org');
  364. $em = Database::getManager();
  365. /** @var LegalRepository $legalTermsRepo */
  366. $legalTermsRepo = $em->getRepository('ChamiloCoreBundle:Legal');
  367. // Get data about the treatment of data
  368. $treatmentTypes = LegalManager::getTreatmentTypeList();
  369. /*foreach ($treatmentTypes as $id => $item) {
  370. $personalData['treatment'][$item]['title'] = get_lang('PersonalData'.ucfirst($item).'Title');
  371. $legalTerm = $legalTermsRepo->findOneByTypeAndLanguage($id, api_get_language_id($user_language));
  372. $legalTermContent = '';
  373. if (!empty($legalTerm[0]) && is_array($legalTerm[0])) {
  374. $legalTermContent = $legalTerm[0]['content'];
  375. }
  376. $personalData['treatment'][$item]['content'] = $legalTermContent;
  377. }*/
  378. $officerName = api_get_configuration_value('data_protection_officer_name');
  379. $officerRole = api_get_configuration_value('data_protection_officer_role');
  380. $officerEmail = api_get_configuration_value('data_protection_officer_email');
  381. if (!empty($officerName)) {
  382. $personalData['officer_name'] = $officerName;
  383. $personalData['officer_role'] = $officerRole;
  384. $personalData['officer_email'] = $officerEmail;
  385. }
  386. $tpl = new Template(null);
  387. $actions = Display::url(
  388. Display::return_icon('excel.png', get_lang('Export'), [], ICON_SIZE_MEDIUM),
  389. api_get_path(WEB_CODE_PATH).'social/personal_data.php?export=1'
  390. );
  391. $tpl->assign('actions', Display::toolbarAction('toolbar', [$actions]));
  392. $termLink = '';
  393. if (api_get_setting('allow_terms_conditions') === 'true') {
  394. $url = api_get_path(WEB_CODE_PATH).'social/terms.php';
  395. $termLink = Display::url(get_lang('Read the Terms and Conditions'), $url);
  396. }
  397. if ($showWarningMessage) {
  398. Display::addFlash(Display::return_message(get_lang('More data available in the database but trunked for efficiency reasons.')));
  399. }
  400. // Block Social Avatar
  401. SocialManager::setSocialUserBlock($tpl, api_get_user_id(), 'messages');
  402. if (api_get_setting('allow_social_tool') === 'true') {
  403. $tpl->assign('social_menu_block', $socialMenuBlock);
  404. } else {
  405. $tpl->assign('social_menu_block', '');
  406. $tpl->assign('personal_data_block', $personalDataContent);
  407. }
  408. $tpl->assign('personal_data', $personalData);
  409. $tpl->assign('permission', $permissionBlock);
  410. $tpl->assign('term_link', $termLink);
  411. $socialLayout = $tpl->get_template('social/personal_data.tpl');
  412. $tpl->display($socialLayout);