index.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CourseBundle\Entity\CForumPost;
  4. use ChamiloSession as Session;
  5. /**
  6. * These files are a complete rework of the forum. The database structure is
  7. * based on phpBB but all the code is rewritten. A lot of new functionalities
  8. * are added:
  9. * - forum categories and forums can be sorted up or down, locked or made invisible
  10. * - consistent and integrated forum administration
  11. * - forum options: are students allowed to edit their post?
  12. * moderation of posts (approval)
  13. * reply only forums (students cannot create new threads)
  14. * multiple forums per group
  15. * - sticky messages
  16. * - new view option: nested view
  17. * - quoting a message.
  18. *
  19. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  20. * @copyright Ghent University
  21. * @copyright Patrick Cool
  22. *
  23. * @package chamilo.forum
  24. */
  25. require_once __DIR__.'/../inc/global.inc.php';
  26. api_protect_course_script(true);
  27. $current_course_tool = TOOL_FORUM;
  28. $htmlHeadXtra[] = '<script>
  29. $(function() {
  30. $(\'.hide-me\').slideUp();
  31. });
  32. function hidecontent(content){
  33. $(content).slideToggle(\'normal\');
  34. }
  35. </script>';
  36. // The section (tabs).
  37. $this_section = SECTION_COURSES;
  38. $nameTools = get_lang('Forums');
  39. $_course = api_get_course_info();
  40. $sessionId = api_get_session_id();
  41. $_user = api_get_user_info();
  42. $hideNotifications = api_get_course_setting('hide_forum_notifications');
  43. $hideNotifications = $hideNotifications == 1;
  44. require_once 'forumfunction.inc.php';
  45. if (api_is_in_gradebook()) {
  46. $interbreadcrumb[] = [
  47. 'url' => Category::getUrl(),
  48. 'name' => get_lang('ToolGradebook'),
  49. ];
  50. }
  51. $search_forum = isset($_GET['search']) ? Security::remove_XSS($_GET['search']) : '';
  52. /* ACTIONS */
  53. $actions = isset($_GET['action']) ? $_GET['action'] : '';
  54. if ($actions === 'add') {
  55. switch ($_GET['content']) {
  56. case 'forum':
  57. $interbreadcrumb[] = [
  58. 'url' => 'index.php?search='.$search_forum.'&'.api_get_cidreq(),
  59. 'name' => get_lang('Forum'),
  60. ];
  61. $interbreadcrumb[] = [
  62. 'url' => '#',
  63. 'name' => get_lang('AddForum'),
  64. ];
  65. break;
  66. case 'forumcategory':
  67. $interbreadcrumb[] = [
  68. 'url' => 'index.php?search='.$search_forum.'&'.api_get_cidreq(),
  69. 'name' => get_lang('Forum'),
  70. ];
  71. $interbreadcrumb[] = [
  72. 'url' => '#',
  73. 'name' => get_lang('AddForumCategory'),
  74. ];
  75. break;
  76. default:
  77. break;
  78. }
  79. } else {
  80. $interbreadcrumb[] = [
  81. 'url' => '#',
  82. 'name' => get_lang('ForumCategories'),
  83. ];
  84. }
  85. // Tool introduction
  86. $introduction = Display::return_introduction_section(TOOL_FORUM);
  87. $form_count = 0;
  88. $formContent = '';
  89. if (api_is_allowed_to_edit(false, true)) {
  90. //if is called from a learning path lp_id
  91. $lp_id = isset($_REQUEST['lp_id']) ? intval($_REQUEST['lp_id']) : null;
  92. $formContent = handle_forum_and_forumcategories($lp_id);
  93. }
  94. // Notification
  95. if ($actions == 'notify' && isset($_GET['content']) && isset($_GET['id'])) {
  96. if (api_get_session_id() != 0 &&
  97. api_is_allowed_to_session_edit(false, true) == false
  98. ) {
  99. api_not_allowed();
  100. }
  101. $return_message = set_notification($_GET['content'], $_GET['id']);
  102. Display::addFlash(Display::return_message($return_message, 'confirm', false));
  103. }
  104. get_whats_new();
  105. $whatsnew_post_info = Session::read('whatsnew_post_info');
  106. /* TRACKING */
  107. Event::event_access_tool(TOOL_FORUM);
  108. $logInfo = [
  109. 'tool' => TOOL_FORUM,
  110. 'tool_id' => 0,
  111. 'tool_id_detail' => 0,
  112. 'action' => !empty($actions) ? $actions : 'list-category',
  113. 'action_details' => isset($_GET['content']) ? $_GET['content'] : '',
  114. ];
  115. Event::registerLog($logInfo);
  116. /*
  117. RETRIEVING ALL THE FORUM CATEGORIES AND FORUMS
  118. note: we do this here just after het handling of the actions to be
  119. sure that we already incorporate the latest changes
  120. */
  121. // Step 1: We store all the forum categories in an array $forum_categories.
  122. $forumCategories = get_forum_categories();
  123. // Step 2: We find all the forums (only the visible ones if it is a student).
  124. // display group forum in general forum tool depending to configuration option
  125. $setting = api_get_setting('display_groups_forum_in_general_tool');
  126. $allCourseForums = get_forums('', '', $setting === 'true');
  127. $user_id = api_get_user_id();
  128. /* RETRIEVING ALL GROUPS AND THOSE OF THE USER */
  129. // The groups of the user.
  130. $groups_of_user = GroupManager::get_group_ids($_course['real_id'], $user_id);
  131. // All groups in the course (and sorting them as the
  132. // id of the group = the key of the array).
  133. if (!api_is_anonymous()) {
  134. $all_groups = GroupManager::get_group_list();
  135. if (is_array($all_groups)) {
  136. foreach ($all_groups as $group) {
  137. $all_groups[$group['id']] = $group;
  138. }
  139. }
  140. }
  141. /* ACTION LINKS */
  142. $actionLeft = null;
  143. //if is called from learning path
  144. if (!empty($_GET['lp_id']) || !empty($_POST['lp_id'])) {
  145. $url = "../lp/lp_controller.php?".api_get_cidreq()
  146. ."&gradebook=&action=add_item&type=step&lp_id='.$lp_id.'#resource_tab-5";
  147. $actionLeft .= Display::url(
  148. Display::return_icon(
  149. 'back.png',
  150. get_lang("BackTo").' '.get_lang("LearningPaths"),
  151. null,
  152. ICON_SIZE_MEDIUM
  153. ),
  154. $url
  155. );
  156. }
  157. if (api_is_allowed_to_edit(false, true)) {
  158. if (is_array($forumCategories) && !empty($forumCategories)) {
  159. $actionLeft .= Display::url(
  160. Display::return_icon(
  161. 'new_forum.png',
  162. get_lang('AddForum'),
  163. null,
  164. ICON_SIZE_MEDIUM
  165. ),
  166. api_get_self().'?'.api_get_cidreq().'&action=add&content=forum&lp_id='.$lp_id
  167. );
  168. }
  169. $actionLeft .= Display::url(
  170. Display::return_icon(
  171. 'new_folder.png',
  172. get_lang('AddForumCategory'),
  173. null,
  174. ICON_SIZE_MEDIUM
  175. ),
  176. api_get_self().'?'.api_get_cidreq().'&action=add&content=forumcategory&lp_id='.$lp_id
  177. );
  178. }
  179. if (!empty($allCourseForums)) {
  180. $actionLeft .= search_link();
  181. }
  182. $actions = Display::toolbarAction('toolbar-forum', [$actionLeft]);
  183. $languages = api_get_language_list_for_flag();
  184. $defaultUserLanguage = ucfirst(api_get_interface_language());
  185. if (isset($_user['language']) && !empty($_user['language'])) {
  186. $defaultUserLanguage = ucfirst($_user['language']);
  187. }
  188. $extraFieldValues = new ExtraFieldValue('user');
  189. $value = $extraFieldValues->get_values_by_handler_and_field_variable(api_get_user_id(), 'langue_cible');
  190. if ($value && isset($value['value']) && !empty($value['value'])) {
  191. $defaultUserLanguage = ucfirst($value['value']);
  192. }
  193. // Create a search-box
  194. $searchFilter = '';
  195. $translate = api_get_configuration_value('translate_html');
  196. if ($translate) {
  197. $form = new FormValidator('search_simple', 'get', api_get_self().'?'.api_get_cidreq(), null, null, 'inline');
  198. $form->addHidden('cidReq', api_get_course_id());
  199. $form->addHidden('id_session', api_get_session_id());
  200. $extraField = new ExtraField('forum_category');
  201. $returnParams = $extraField->addElements(
  202. $form,
  203. null,
  204. [], //exclude
  205. false, // filter
  206. false, // tag as select
  207. ['language'], //show only fields
  208. [], // order fields
  209. [], // extra data
  210. false,
  211. false,
  212. [],
  213. [],
  214. true //$addEmptyOptionSelects = false,
  215. );
  216. $form->setDefaults(['extra_language' => $defaultUserLanguage]);
  217. $searchFilter = $form->returnForm();
  218. }
  219. // Fixes error if there forums with no category.
  220. $forumsInNoCategory = get_forums_in_category(0);
  221. if (!empty($forumsInNoCategory)) {
  222. $forumCategories = array_merge(
  223. $forumCategories,
  224. [
  225. [
  226. 'cat_id' => 0,
  227. 'session_id' => 0,
  228. 'visibility' => 1,
  229. 'cat_comment' => null,
  230. ],
  231. ]
  232. );
  233. }
  234. /* Display Forum Categories and the Forums in it */
  235. // Step 3: We display the forum_categories first.
  236. $listForumCategory = [];
  237. $forumCategoryInfo = [];
  238. if (is_array($forumCategories)) {
  239. foreach ($forumCategories as $forumCategory) {
  240. $forumCategoryInfo['id'] = $forumCategory['cat_id'];
  241. if (empty($forumCategory['cat_title'])) {
  242. $forumCategoryInfo['title'] = get_lang('WithoutCategory');
  243. } else {
  244. $forumCategoryInfo['title'] = $forumCategory['cat_title'];
  245. }
  246. $forumCategoryInfo['extra_fields'] = $forumCategory['extra_fields'];
  247. $forumCategoryInfo['icon_session'] = api_get_session_image($forumCategory['session_id'], $_user['status']);
  248. // Validation when belongs to a session
  249. $forumCategoryInfo['description'] = $forumCategory['cat_comment'];
  250. $forumCategory['session_display'] = null;
  251. if (empty($sessionId) && !empty($forumCategory['session_name'])) {
  252. $forumCategory['session_display'] = ' ('.Security::remove_XSS($forumCategory['session_name']).')';
  253. }
  254. $tools = null;
  255. $idCategory = (int) $forumCategory['cat_id'];
  256. $forumCategoryInfo['url'] = 'viewforumcategory.php?'.api_get_cidreq().'&forumcategory='.$idCategory;
  257. if (!empty($idCategory)) {
  258. if (api_is_allowed_to_edit(false, true) &&
  259. !($forumCategory['session_id'] == 0 && $sessionId != 0)
  260. ) {
  261. $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq()
  262. .'&action=edit&content=forumcategory&id='.$idCategory
  263. .'">'.Display::return_icon(
  264. 'edit.png',
  265. get_lang('Edit'),
  266. [],
  267. ICON_SIZE_SMALL
  268. )
  269. .'</a>';
  270. $tools .= '<a href="'.api_get_self().'?'.api_get_cidreq()
  271. .'&action=delete&content=forumcategory&id='.$idCategory
  272. ."\" onclick=\"javascript:if(!confirm('"
  273. .addslashes(api_htmlentities(
  274. get_lang('DeleteForumCategory'),
  275. ENT_QUOTES
  276. ))
  277. ."')) return false;\">"
  278. .Display::return_icon(
  279. 'delete.png',
  280. get_lang('Delete'),
  281. [],
  282. ICON_SIZE_SMALL
  283. )
  284. .'</a>';
  285. $tools .= return_visible_invisible_icon(
  286. 'forumcategory',
  287. $idCategory,
  288. $forumCategory['visibility']
  289. );
  290. $tools .= return_lock_unlock_icon(
  291. 'forumcategory',
  292. $idCategory,
  293. $forumCategory['locked']
  294. );
  295. $tools .= return_up_down_icon(
  296. 'forumcategory',
  297. $idCategory,
  298. $forumCategories
  299. );
  300. }
  301. }
  302. $forumCategoryInfo['tools'] = $tools;
  303. $forumCategoryInfo['forums'] = [];
  304. // The forums in this category.
  305. $forumInfo = [];
  306. $forumsInCategory = get_forums_in_category($forumCategory['cat_id']);
  307. if (!empty($forumsInCategory)) {
  308. $forumsDetailsList = [];
  309. // We display all the forums in this category.
  310. foreach ($allCourseForums as $forum) {
  311. // Here we clean the whatnew_post_info array a little bit because to display the icon we
  312. // test if $whatsnew_post_info[$forum['forum_id']] is empty or not.
  313. if (isset($forum['forum_id'])) {
  314. if (!empty($whatsnew_post_info)) {
  315. if (isset($whatsnew_post_info[$forum['forum_id']]) &&
  316. is_array($whatsnew_post_info[$forum['forum_id']])
  317. ) {
  318. foreach ($whatsnew_post_info[$forum['forum_id']] as $key_thread_id => $new_post_array) {
  319. if (empty($whatsnew_post_info[$forum['forum_id']][$key_thread_id])) {
  320. unset($whatsnew_post_info[$forum['forum_id']][$key_thread_id]);
  321. unset($_SESSION['whatsnew_post_info'][$forum['forum_id']][$key_thread_id]);
  322. }
  323. }
  324. }
  325. }
  326. }
  327. // Note: This can be speed up if we transform the $allCourseForums
  328. // to an array that uses the forum_category as the key.
  329. if (isset($forum['forum_category']) && $forum['forum_category'] == $forumCategory['cat_id']) {
  330. $show_forum = false;
  331. // SHOULD WE SHOW THIS PARTICULAR FORUM
  332. // you are teacher => show forum
  333. if (api_is_allowed_to_edit(false, true)) {
  334. $show_forum = true;
  335. } else {
  336. // you are not a teacher
  337. // it is not a group forum => show forum
  338. // (invisible forums are already left out see get_forums function)
  339. if ($forum['forum_of_group'] == '0') {
  340. $show_forum = true;
  341. } else {
  342. $show_forum = GroupManager::user_has_access(
  343. $user_id,
  344. $forum['forum_of_group'],
  345. GroupManager::GROUP_TOOL_FORUM
  346. );
  347. }
  348. }
  349. if ($show_forum) {
  350. $form_count++;
  351. $mywhatsnew_post_info = isset($whatsnew_post_info[$forum['forum_id']])
  352. ? $whatsnew_post_info[$forum['forum_id']]
  353. : null;
  354. $forumInfo['id'] = $forum['forum_id'];
  355. $forumInfo['forum_of_group'] = $forum['forum_of_group'];
  356. $forumInfo['title'] = $forum['forum_title'];
  357. $forumInfo['forum_image'] = null;
  358. // Showing the image
  359. if (!empty($forum['forum_image'])) {
  360. $image_path = api_get_path(WEB_COURSE_PATH).api_get_course_path().'/upload/forum/images/'
  361. .$forum['forum_image'];
  362. $image_size = api_getimagesize($image_path);
  363. $img_attributes = '';
  364. if (!empty($image_size)) {
  365. $forumInfo['forum_image'] = $image_path;
  366. }
  367. }
  368. // Validation when belongs to a session
  369. $forumInfo['icon_session'] = api_get_session_image(
  370. $forum['session_id'],
  371. $_user['status']
  372. );
  373. if ($forum['forum_of_group'] != '0') {
  374. $my_all_groups_forum_name = isset($all_groups[$forum['forum_of_group']]['name'])
  375. ? $all_groups[$forum['forum_of_group']]['name']
  376. : null;
  377. $my_all_groups_forum_id = isset($all_groups[$forum['forum_of_group']]['id'])
  378. ? $all_groups[$forum['forum_of_group']]['id']
  379. : null;
  380. $group_title = api_substr($my_all_groups_forum_name, 0, 30);
  381. $forumInfo['forum_group_title'] = $group_title;
  382. }
  383. $forum['forum_of_group'] == 0 ? $groupid = '' : $groupid = $forum['forum_of_group'];
  384. $forumInfo['visibility'] = $forum['visibility'];
  385. $forumInfo['number_threads'] = isset($forum['number_of_threads'])
  386. ? (int) $forum['number_of_threads']
  387. : 0;
  388. //$number_posts = isset($forum['number_of_posts']) ? $forum['number_of_posts'] : 0;
  389. $linkForum = api_get_path(WEB_CODE_PATH).'forum/viewforum.php?'.api_get_cidreq()
  390. .'&gidReq='.$groupid.'&forum='.$forum['forum_id'];
  391. $forumInfo['url'] = $linkForum;
  392. if (!empty($forum['start_time']) && !empty($forum['end_time'])) {
  393. $res = api_is_date_in_date_range($forum['start_time'], $forum['end_time']);
  394. if (!$res) {
  395. $linkForum = $forum['forum_title'];
  396. }
  397. }
  398. $forumInfo['description'] = Security::remove_XSS($forum['forum_comment']);
  399. if ($forum['moderated'] == 1 && api_is_allowed_to_edit(false, true)) {
  400. $waitingCount = getCountPostsWithStatus(
  401. CForumPost::STATUS_WAITING_MODERATION,
  402. $forum
  403. );
  404. if (!empty($waitingCount)) {
  405. $forumInfo['moderation'] = $waitingCount;
  406. }
  407. }
  408. $toolActions = null;
  409. $forumInfo['alert'] = null;
  410. // The number of topics and posts.
  411. if ($hideNotifications == false) {
  412. // The number of topics and posts.
  413. if ($forum['forum_of_group'] !== '0') {
  414. if (is_array($mywhatsnew_post_info) && !empty($mywhatsnew_post_info)) {
  415. $forumInfo['alert'] = ' '.
  416. Display::return_icon(
  417. 'alert.png',
  418. get_lang('Forum'),
  419. null,
  420. ICON_SIZE_SMALL
  421. );
  422. }
  423. } else {
  424. if (is_array($mywhatsnew_post_info) && !empty($mywhatsnew_post_info)) {
  425. $forumInfo['alert'] = ' '.Display::return_icon(
  426. 'alert.png',
  427. get_lang('Forum'),
  428. null,
  429. ICON_SIZE_SMALL
  430. );
  431. }
  432. }
  433. }
  434. $poster_id = null;
  435. // The last post in the forum.
  436. if (isset($forum['last_poster_name']) && $forum['last_poster_name'] != '') {
  437. $name = $forum['last_poster_name'];
  438. $poster_id = 0;
  439. $username = "";
  440. } else {
  441. if (isset($forum['last_poster_firstname'])) {
  442. $name = api_get_person_name(
  443. $forum['last_poster_firstname'],
  444. $forum['last_poster_lastname']
  445. );
  446. $poster_id = $forum['last_poster_id'];
  447. $userinfo = api_get_user_info($poster_id);
  448. $username = sprintf(
  449. get_lang('LoginX'),
  450. $userinfo['username']
  451. );
  452. }
  453. }
  454. $forumInfo['last_poster_id'] = $poster_id;
  455. if (!empty($forum['last_poster_id'])) {
  456. $forumInfo['last_poster_date'] = api_convert_and_format_date($forum['last_post_date']);
  457. $forumInfo['last_poster_user'] = display_user_link($poster_id, $name, null, $username);
  458. $forumInfo['last_post_title'] = Security::remove_XSS(cut($forum['last_post_title'], 140));
  459. $forumInfo['last_post_text'] = Security::remove_XSS(cut($forum['last_post_text'], 140));
  460. }
  461. if (api_is_allowed_to_edit(false, true)
  462. && !($forum['session_id'] == 0 && $sessionId != 0)
  463. ) {
  464. $toolActions .= '<a href="'.api_get_self().'?'.api_get_cidreq()
  465. .'&action=edit&content=forum&id='.$forum['forum_id'].'">'
  466. .Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL)
  467. .'</a>';
  468. $toolActions .= '<a href="'.api_get_self().'?'.api_get_cidreq()
  469. .'&action=delete&content=forum&id='.$forum['forum_id']
  470. ."\" onclick=\"javascript:if(!confirm('".addslashes(
  471. api_htmlentities(get_lang('DeleteForum'), ENT_QUOTES)
  472. )
  473. ."')) return false;\">"
  474. .Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL)
  475. .'</a>';
  476. $toolActions .= return_visible_invisible_icon(
  477. 'forum',
  478. $forum['forum_id'],
  479. $forum['visibility']
  480. );
  481. $toolActions .= return_lock_unlock_icon(
  482. 'forum',
  483. $forum['forum_id'],
  484. $forum['locked']
  485. );
  486. $toolActions .= return_up_down_icon(
  487. 'forum',
  488. $forum['forum_id'],
  489. $forumsInCategory
  490. );
  491. }
  492. $iconnotify = 'notification_mail_na.png';
  493. $session_forum_notification = isset($_SESSION['forum_notification']['forum'])
  494. ? $_SESSION['forum_notification']['forum']
  495. : false;
  496. if (is_array($session_forum_notification)) {
  497. if (in_array($forum['forum_id'], $session_forum_notification)) {
  498. $iconnotify = 'notification_mail.png';
  499. }
  500. }
  501. if (!api_is_anonymous() && api_is_allowed_to_session_edit(false, true) && $hideNotifications == false) {
  502. $toolActions .= '<a href="'.api_get_self().'?'.api_get_cidreq()
  503. .'&action=notify&content=forum&id='.$forum['forum_id'].'">'
  504. .Display::return_icon($iconnotify, get_lang('NotifyMe'), null, ICON_SIZE_SMALL)
  505. .'</a>';
  506. }
  507. $forumInfo['tools'] = $toolActions;
  508. $forumsDetailsList[] = $forumInfo;
  509. }
  510. }
  511. }
  512. $forumCategoryInfo['forums'] = $forumsDetailsList;
  513. }
  514. // Don't show empty categories (for students)
  515. if (!api_is_allowed_to_edit()) {
  516. if (empty($forumCategoryInfo['forums'])) {
  517. continue;
  518. }
  519. }
  520. $listForumCategory[] = $forumCategoryInfo;
  521. }
  522. }
  523. $tpl = new Template($nameTools);
  524. $tpl->assign('introduction', $introduction);
  525. $tpl->assign('actions', $actions);
  526. $tpl->assign('data', $listForumCategory);
  527. $tpl->assign('form_content', $formContent);
  528. $tpl->assign('search_filter', $searchFilter);
  529. $tpl->assign('default_user_language', $defaultUserLanguage);
  530. $tpl->assign('languages', $languages);
  531. $extraFieldValue = new ExtraFieldValue('course');
  532. $value = $extraFieldValue->get_values_by_handler_and_field_variable(api_get_course_int_id(), 'global_forum');
  533. if ($value && isset($value['value']) && $value['value'] == 1) {
  534. $layout = $tpl->get_template('forum/global_list.tpl');
  535. } else {
  536. $layout = $tpl->get_template('forum/list.tpl');
  537. }
  538. $tpl->display($layout);