profile.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <?php
  2. // $Id: profile.php 9548 2006-10-18 08:19:15Z elixir_inter $
  3. /*
  4. ==============================================================================
  5. Dokeos - elearning and course management software
  6. Copyright (c) 2004 Dokeos S.A.
  7. Copyright (c) 2003 Ghent University (UGent)
  8. Copyright (c) 2001 Universite catholique de Louvain (UCL)
  9. Copyright (c) Roan Embrechts (Vrije Universiteit Brussel)
  10. For a full list of contributors, see "credits.txt".
  11. The full license can be read in "license.txt".
  12. This program is free software; you can redistribute it and/or
  13. modify it under the terms of the GNU General Public License
  14. as published by the Free Software Foundation; either version 2
  15. of the License, or (at your option) any later version.
  16. See the GNU General Public License for more details.
  17. Contact address: Dokeos, 44 rue des palais, B-1030 Brussels, Belgium
  18. Mail: info@dokeos.com
  19. ==============================================================================
  20. */
  21. /**
  22. ==============================================================================
  23. * This file displays the user's profile,
  24. * optionally it allows users to modify their profile as well.
  25. *
  26. * See inc/conf/profile.conf.inc.php to modify settings
  27. *
  28. * @package dokeos.auth
  29. ==============================================================================
  30. */
  31. /*
  32. ==============================================================================
  33. INIT SECTION
  34. ==============================================================================
  35. */
  36. $langFile = 'registration';
  37. $cidReset = true;
  38. require ('../inc/global.inc.php');
  39. require_once (api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php');
  40. $this_section = SECTION_MYPROFILE;
  41. api_block_anonymous_users();
  42. $htmlHeadXtra[] = '<script type="text/javascript">
  43. function confirmation(name)
  44. {
  45. if (confirm("'.get_lang('AreYouSureToDelete').' " + name + " ?"))
  46. {return true;}
  47. else
  48. {return false;}
  49. }
  50. </script>';
  51. if (!empty ($_GET['coursePath']))
  52. {
  53. $course_url = api_get_path(WEB_COURSE_PATH).$_GET['coursePath'].'/index.php';
  54. $interbreadcrumb[] = array ('url' => $course_url, 'name' => $_GET['courseCode']);
  55. }
  56. /*
  57. -----------------------------------------------------------
  58. Configuration file
  59. -----------------------------------------------------------
  60. */
  61. require_once (api_get_path(CONFIGURATION_PATH).'profile.conf.inc.php');
  62. /*
  63. -----------------------------------------------------------
  64. Libraries
  65. -----------------------------------------------------------
  66. */
  67. include_once (api_get_path(LIBRARY_PATH).'fileManage.lib.php');
  68. include_once (api_get_path(LIBRARY_PATH).'fileUpload.lib.php');
  69. if (is_profile_editable())
  70. $tool_name = get_lang('ModifProfile');
  71. else
  72. $tool_name = get_lang('ViewProfile');
  73. $table_user = Database :: get_main_table(MAIN_USER_TABLE);
  74. /*
  75. -----------------------------------------------------------
  76. Form
  77. -----------------------------------------------------------
  78. */
  79. /*
  80. * Get initial values for all fields.
  81. */
  82. $sql = "SELECT * FROM $table_user WHERE user_id = '$_uid'";
  83. $result = api_sql_query($sql, __FILE__, __LINE__);
  84. if ($result)
  85. {
  86. $user_data = mysql_fetch_array($result, MYSQL_ASSOC);
  87. if (is_null($user_data['language']))
  88. $user_data['language'] = api_get_setting('platformLanguage');
  89. }
  90. /*
  91. * Initialize the form.
  92. */
  93. $form = new FormValidator('profile', 'post', "{$_SERVER['PHP_SELF']}?{$_SERVER['QUERY_STRING']}", null, array('style' => 'width: 60%; float: '.($text_dir=='rtl'?'right;':'left;')));
  94. /* Make sure this is the first submit on the form, even though it is hidden!
  95. * Otherwise, if a user has productions and presses ENTER to submit, he will
  96. * attempt to delete the first production in the list. */
  97. if (is_profile_editable())
  98. $form->addElement('submit', null, get_lang('Ok'), array('style' => 'visibility:hidden;'));
  99. // LAST NAME and FIRST NAME
  100. $form->addElement('text', 'lastname', get_lang('Lastname'), array('size' => 40));
  101. $form->addElement('text', 'firstname', get_lang('Firstname'), array('size' => 40));
  102. if (api_get_setting('profile', 'name') !== 'true')
  103. $form->freeze(array('lastname', 'firstname'));
  104. $form->applyFilter(array('lastname', 'firstname'), 'stripslashes');
  105. $form->applyFilter(array('lastname', 'firstname'), 'trim');
  106. $form->addRule('lastname' , get_lang('ThisFieldIsRequired'), 'required');
  107. $form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
  108. // OFFICIAL CODE
  109. if (CONFVAL_ASK_FOR_OFFICIAL_CODE)
  110. {
  111. $form->addElement('text', 'official_code', get_lang('OfficialCode'), array('size' => 40));
  112. if (api_get_setting('profile', 'officialcode') !== 'true')
  113. $form->freeze('official_code');
  114. $form->applyFilter('official_code', 'stripslashes');
  115. $form->applyFilter('official_code', 'trim');
  116. if (api_get_setting('registration', 'officialcode') == 'true')
  117. $form->addRule('official_code', get_lang('ThisFieldIsRequired'), 'required');
  118. }
  119. // EMAIL
  120. $form->addElement('text', 'email', get_lang('Email'), array('size' => 40));
  121. if (api_get_setting('profile', 'email') !== 'true')
  122. $form->freeze('email');
  123. $form->applyFilter('email', 'stripslashes');
  124. $form->applyFilter('email', 'trim');
  125. if (api_get_setting('registration', 'email') == 'true')
  126. $form->addRule('email', get_lang('ThisFieldIsRequired'), 'required');
  127. $form->addRule('email', get_lang('EmailWrong'), 'email');
  128. // PHONE
  129. $form->addElement('text', 'phone', get_lang('phone'), array('size' => 20));
  130. if (api_get_setting('profile', 'phone') !== 'true')
  131. $form->freeze('phone');
  132. $form->applyFilter('phone', 'stripslashes');
  133. $form->applyFilter('phone', 'trim');
  134. /*if (api_get_setting('registration', 'phone') == 'true')
  135. $form->addRule('phone', get_lang('ThisFieldIsRequired'), 'required');
  136. $form->addRule('phone', get_lang('EmailWrong'), 'email');*/
  137. // PICTURE
  138. if (is_profile_editable() && api_get_setting('profile', 'picture') == 'true')
  139. {
  140. $form->addElement('file', 'picture', (get_user_image($_uid) != '' ? get_lang('UpdateImage') : get_lang('AddImage')));
  141. $form->add_progress_bar();
  142. if( strlen($user_data['picture_uri']) > 0)
  143. {
  144. $form->addElement('checkbox', 'remove_picture', null, get_lang('DelImage'));
  145. }
  146. $form->addRule('picture', get_lang('OnlyImagesAllowed'), 'mimetype', array('image/gif', 'image/jpeg', 'image/png'));
  147. }
  148. // USERNAME
  149. $form->addElement('text', 'username', get_lang('Username'), array('size' => 40));
  150. if (api_get_setting('profile', 'login') !== 'true')
  151. $form->freeze('username');
  152. $form->applyFilter('username', 'stripslashes');
  153. $form->applyFilter('username', 'trim');
  154. $form->addRule('username', get_lang('ThisFieldIsRequired'), 'required');
  155. $form->addRule('username', get_lang('UsernameWrong'), 'username');
  156. $form->addRule('username', get_lang('UserTaken'), 'username_available', $user_data['username']);
  157. // LANGUAGE
  158. $form->addElement('select_language', 'language', get_lang('Language'));
  159. if (api_get_setting('profile', 'language') !== 'true')
  160. $form->freeze('language');
  161. // EXTENDED PROFILE
  162. if (api_get_setting('extended_profile') == 'true')
  163. {
  164. $form->addElement('static', null, '<em>'.get_lang('OptionalTextFields').'</em>');
  165. // MY COMPETENCES
  166. $form->addElement('textarea', 'competences', get_lang('MyCompetences'), array('cols' => 30, 'rows' => 2));
  167. // MY DIPLOMAS
  168. $form->addElement('textarea', 'diplomas', get_lang('MyDiplomas'), array('cols' => 30, 'rows' => 2));
  169. // WHAT I AM ABLE TO TEACH
  170. $form->addElement('textarea', 'teach', get_lang('MyTeach'), array('cols' => 30, 'rows' => 2));
  171. // MY PRODUCTIONS
  172. $form->addElement('file', 'production', get_lang('MyProductions'));
  173. if ($production_list = build_production_list($_uid))
  174. $form->addElement('static', 'productions', null, $production_list);
  175. // MY PERSONAL OPEN AREA
  176. $form->add_html_editor('openarea', get_lang('MyPersonalOpenArea'), false);
  177. $form->applyFilter(array('competences', 'diplomas', 'teach', 'openarea'), 'stripslashes');
  178. $form->applyFilter(array('competences', 'diplomas', 'teach'), 'trim'); // openarea is untrimmed for maximum openness
  179. }
  180. // PASSWORD
  181. if (is_profile_editable() && api_get_setting('profile', 'password') == 'true')
  182. {
  183. $form->addElement('static', null, null, '<em>'.get_lang('Enter2passToChange').'</em>');
  184. $form->addElement('password', 'password1', get_lang('Pass'), array('size' => 40));
  185. $form->addElement('password', 'password2', get_lang('Confirmation'), array('size' => 40));
  186. // user must enter identical password twice so we can prevent some user errors
  187. $form->addRule(array('password1', 'password2'), get_lang('PassTwo'), 'compare');
  188. if (CHECK_PASS_EASY_TO_FIND)
  189. $form->addRule('password1', get_lang('PassTooEasy').': '.api_generate_password(), 'callback', 'api_check_password');
  190. }
  191. // SUBMIT
  192. if (is_profile_editable())
  193. {
  194. $form->addElement('submit', 'apply_change', get_lang('Ok'));
  195. }
  196. else
  197. {
  198. $form->freeze();
  199. }
  200. /*
  201. * Set initial values for all fields.
  202. */
  203. $form->setDefaults($user_data);
  204. /*
  205. ==============================================================================
  206. FUNCTIONS
  207. ==============================================================================
  208. */
  209. /*
  210. -----------------------------------------------------------
  211. LOGIC FUNCTIONS
  212. -----------------------------------------------------------
  213. */
  214. /**
  215. * Can a user edit his/her profile?
  216. *
  217. * @return boolean Editability of the profile
  218. */
  219. function is_profile_editable()
  220. {
  221. return $GLOBALS['profileIsEditable'];
  222. }
  223. /*
  224. -----------------------------------------------------------
  225. USER IMAGE FUNCTIONS
  226. -----------------------------------------------------------
  227. */
  228. /**
  229. * Get a user's display picture. If the user doesn't have a picture, this
  230. * function will return an empty string.
  231. *
  232. * @param $_uid User id
  233. * @return The uri to the picture
  234. */
  235. function get_user_image($_uid)
  236. {
  237. $table_user = Database :: get_main_table(MAIN_USER_TABLE);
  238. $sql = "SELECT picture_uri FROM $table_user WHERE user_id = '$_uid'";
  239. $result = api_sql_query($sql, __FILE__, __LINE__);
  240. if ($result && $row = mysql_fetch_array($result, MYSQL_ASSOC))
  241. $image = trim($row['picture_uri']);
  242. else
  243. $image = '';
  244. return $image;
  245. }
  246. /**
  247. * Upload a submitted user image.
  248. *
  249. * @param $_uid User id
  250. * @return The filename of the new picture or FALSE if the upload has failed
  251. */
  252. function upload_user_image($_uid)
  253. {
  254. /* Originally added by Miguel (miguel@cesga.es) - 2003-11-04
  255. * Code Refactoring by Hugues Peeters (hugues.peeters@claroline.net) - 2003-11-24
  256. * Moved inside a function and refactored by Thomas Corthals - 2005-11-04
  257. */
  258. $image_repository = api_get_path(SYS_CODE_PATH).'upload/users/';
  259. $existing_image = get_user_image($_uid);
  260. $file_extension = explode('.', $_FILES['picture']['name']);
  261. $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
  262. if (!file_exists($image_repository))
  263. mkpath($image_repository);
  264. if ($existing_image != '')
  265. {
  266. if (KEEP_THE_NAME_WHEN_CHANGE_IMAGE)
  267. {
  268. $picture_filename = $existing_image;
  269. $old_picture_filename = 'saved_'.date('Y_m_d_H_i_s').'_'.uniqid('').'_'.$existing_image;
  270. }
  271. else
  272. {
  273. $old_picture_filename = $existing_image;
  274. $picture_filename = (PREFIX_IMAGE_FILENAME_WITH_UID ? 'u'.$_uid.'_' : '').uniqid('').'.'.$file_extension;
  275. }
  276. if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE)
  277. rename($image_repository.$existing_image, $image_repository.$old_picture_filename);
  278. else
  279. unlink($image_repository.$existing_image);
  280. }
  281. else
  282. {
  283. $picture_filename = (PREFIX_IMAGE_FILENAME_WITH_UID ? $_uid.'_' : '').uniqid('').'.'.$file_extension;
  284. }
  285. if (move_uploaded_file($_FILES['picture']['tmp_name'], $image_repository.$picture_filename))
  286. return $picture_filename;
  287. return false; // this should be returned if anything went wrong with the upload
  288. }
  289. /**
  290. * Remove an existing user image.
  291. *
  292. * @param $_uid User id
  293. */
  294. function remove_user_image($_uid)
  295. {
  296. $image_repository = api_get_path(SYS_CODE_PATH).'upload/users/';
  297. $image = get_user_image($_uid);
  298. if ($image != '')
  299. {
  300. if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE)
  301. rename($image_repository.$image, $image_repository.'deleted_'.date('Y_m_d_H_i_s').'_'.$image);
  302. else
  303. unlink($image_repository.$image);
  304. }
  305. }
  306. /*
  307. -----------------------------------------------------------
  308. PRODUCTIONS FUNCTIONS
  309. -----------------------------------------------------------
  310. */
  311. /**
  312. * Returns an XHTML formatted list of productions for a user, or FALSE if he
  313. * doesn't have any.
  314. *
  315. * If there has been a request to remove a production, the function will return
  316. * without building the list unless forced to do so by the optional second
  317. * parameter. This increases performance by avoiding to read through the
  318. * productions on the filesystem before the removal request has been carried
  319. * out because they'll have to be re-read afterwards anyway.
  320. *
  321. * @param $_uid User id
  322. * @param $force Optional parameter to force building after a removal request
  323. * @return A string containing the XHTML code to dipslay the production list, or FALSE
  324. */
  325. function build_production_list($_uid, $force = false)
  326. {
  327. if (!$force && $_POST['remove_production'])
  328. return true; // postpone reading from the filesystem
  329. $productions = get_user_productions($_uid);
  330. if (empty($productions))
  331. return false;
  332. $production_dir = api_get_path(WEB_CODE_PATH)."upload/users/$_uid/";
  333. $del_image = api_get_path(WEB_CODE_PATH).'img/delete.gif';
  334. $del_text = get_lang('Delete');
  335. $production_list = '<ul id="productions">';
  336. foreach ($productions as $file)
  337. {
  338. $production_list .= '<li><a href="'.$production_dir.urlencode($file).'" target="_blank">'.htmlentities($file).'</a>';
  339. $production_list .= '<input type="image" name="remove_production['.urlencode($file).']" src="'.$del_image.'" alt="'.$del_text.'" title="'.$del_text.' '.htmlentities($file).'" onclick="return confirmation(\''.htmlentities($file).'\');" /></li>';
  340. }
  341. $production_list .= '</ul>';
  342. return $production_list;
  343. }
  344. /**
  345. * Returns an array with the user's productions.
  346. *
  347. * @param $_uid User id
  348. * @return An array containing the user's productions
  349. */
  350. function get_user_productions($_uid)
  351. {
  352. $production_repository = api_get_path(SYS_CODE_PATH)."upload/users/$_uid/";
  353. $productions = array();
  354. if (is_dir($production_repository))
  355. {
  356. $handle = opendir($production_repository);
  357. while ($file = readdir($handle))
  358. {
  359. if ($file == '.' || $file == '..' || $file == '.htaccess')
  360. continue; // skip current/parent directory and .htaccess
  361. $productions[] = $file;
  362. }
  363. }
  364. return $productions; // can be an empty array
  365. }
  366. /**
  367. * Upload a submitted user production.
  368. *
  369. * @param $_uid User id
  370. * @return The filename of the new production or FALSE if the upload has failed
  371. */
  372. function upload_user_production($_uid)
  373. {
  374. $production_repository = api_get_path(SYS_CODE_PATH)."upload/users/$_uid/";
  375. if (!file_exists($production_repository))
  376. mkpath($production_repository);
  377. $filename = replace_dangerous_char($_FILES['production']['name']);
  378. $filename = php2phps($filename);
  379. if (move_uploaded_file($_FILES['production']['tmp_name'], $production_repository.$filename))
  380. return $filename;
  381. return false; // this should be returned if anything went wrong with the upload
  382. }
  383. /**
  384. * Remove a user production.
  385. *
  386. * @param $_uid User id
  387. * @param $production The production to remove
  388. */
  389. function remove_user_production($_uid, $production)
  390. {
  391. unlink(api_get_path(SYS_CODE_PATH)."upload/users/$_uid/$production");
  392. }
  393. /*
  394. ==============================================================================
  395. MAIN CODE
  396. ==============================================================================
  397. */
  398. if ($_SESSION['profile_update'])
  399. {
  400. $update_success = ($_SESSION['profile_update'] == 'success');
  401. unset($_SESSION['profile_update']);
  402. }
  403. elseif ($_POST['remove_production'])
  404. {
  405. foreach (array_keys($_POST['remove_production']) as $production)
  406. remove_user_production($_uid, urldecode($production));
  407. if ($production_list = build_production_list($_uid, true))
  408. $form->insertElementBefore($form->createElement('static', null, null, $production_list), 'productions');
  409. $form->removeElement('productions');
  410. $file_deleted = true;
  411. }
  412. elseif ($form->validate())
  413. {
  414. $user_data = $form->exportValues();
  415. // set password if a new one was provided
  416. if ($user_data['password1'])
  417. $password = $user_data['password1'];
  418. // upload picture if a new one is provided
  419. if ($_FILES['picture']['size'])
  420. {
  421. if ($new_picture = upload_user_image($_uid))
  422. $user_data['picture_uri'] = $new_picture;
  423. }
  424. // remove existing picture if asked
  425. elseif ($user_data['remove_picture'])
  426. {
  427. remove_user_image($_uid);
  428. $user_data['picture_uri'] = '';
  429. }
  430. // upload production if a new one is provided
  431. if ($_FILES['production']['size'])
  432. upload_user_production($_uid);
  433. // remove values that shouldn't go in the database
  434. unset($user_data['password1'], $user_data['password2'], $user_data['MAX_FILE_SIZE'],
  435. $user_data['remove_picture'], $user_data['apply_change']);
  436. // build SQL query
  437. $sql = "UPDATE $table_user SET";
  438. foreach($user_data as $key => $value)
  439. {
  440. $sql .= " $key = '".addslashes($value)."',";
  441. }
  442. if (isset($password))
  443. {
  444. if ($userPasswordCrypted)
  445. {
  446. $sql .= " password = MD5('".addslashes($password)."')";
  447. }
  448. else
  449. {
  450. $sql .= " password = '".addslashes($password)."'";
  451. }
  452. }
  453. else // remove trailing , from the query we have so far
  454. {
  455. $sql = rtrim($sql, ',');
  456. }
  457. $sql .= " WHERE user_id = '$_uid'";
  458. api_sql_query($sql, __FILE__, __LINE__);
  459. // re-init the system to take new settings into account
  460. $uidReset = true;
  461. include (api_get_path(INCLUDE_PATH).'local.inc.php');
  462. $_SESSION['profile_update'] = 'success';
  463. header("Location: http://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}?{$_SERVER['QUERY_STRING']}");
  464. exit;
  465. }
  466. /*
  467. ==============================================================================
  468. MAIN DISPLAY SECTION
  469. ==============================================================================
  470. */
  471. Display :: display_header(get_lang('ModifyProfile'));
  472. if ($file_deleted)
  473. {
  474. Display :: display_normal_message(get_lang('FileDeleted'));
  475. }
  476. elseif ($update_success)
  477. {
  478. Display :: display_normal_message(get_lang('ProfileReg'));
  479. }
  480. // USER PICTURE
  481. $image = get_user_image($_uid);
  482. $image_file = ($image != '' ? api_get_path(WEB_CODE_PATH)."upload/users/$image" : api_get_path(WEB_CODE_PATH).'img/unknown.jpg');
  483. $image_size = @getimagesize($image_file);
  484. $img_attributes = 'src="'.$image_file.'?rand='.time().'" '
  485. .'alt="'.$user_data['lastname'].' '.$user_data['firstname'].'" '
  486. .'style="float:'.($text_dir == 'rtl' ? 'left' : 'right').'; padding:5px;" ';
  487. if ($image_size[0] > 300) //limit display width to 300px
  488. $img_attributes .= 'width="300" ';
  489. echo '<img '.$img_attributes.'/>';
  490. $form->display();
  491. echo '<div style="clear:both; border-top:thin solid; padding-top:2px;">
  492. <a href="'.api_get_path(WEB_CODE_PATH).'tracking/personnalLog.php">'.get_lang('MyStats').'</a>
  493. | <a href="'.api_get_path(WEB_CODE_PATH).'auth/courses.php">'.get_lang('MyCourses').'</a></div>';
  494. Display :: display_footer();
  495. ?>