index.php 24 KB

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