UI Improvements + lots of bugfixes */ require_once __DIR__.'/../inc/global.inc.php'; api_protect_course_script(true); require_once 'forumfunction.inc.php'; $nameTools = get_lang('Forum'); $forumUrl = api_get_path(WEB_CODE_PATH).'forum/'; // Are we in a lp ? $origin = api_get_origin(); $_user = api_get_user_info(); $my_search = null; $moveForm = ''; $forumId = isset($_GET['forum']) ? (int) $_GET['forum'] : 0; $postId = isset($_GET['post_id']) ? $_GET['post_id'] : 0; $threadId = isset($_GET['thread']) ? (int) $_GET['thread'] : 0; $repo = Container::getForumRepository(); $forumEntity = null; if (!empty($forumId)) { /** @var CForumForum $forumEntity */ $forumEntity = $repo->find($forumId); } $repoThread = Container::getForumThreadRepository(); /** @var CForumThread $threadEntity */ $threadEntity = $repoThread->find($threadId); if (empty($threadEntity)) { $url = api_get_path(WEB_CODE_PATH).'forum/viewforum.php?'.api_get_cidreq().'&forum='.$forumId; header('Location: '.$url); exit; } $repoPost = Container::getForumPostRepository(); $postEntity = null; if (!empty($postId)) { /** @var CForumPost $postEntity */ $postEntity = $repoPost->find($postId); } $courseEntity = api_get_course_entity(api_get_course_int_id()); $sessionEntity = api_get_session_entity(api_get_session_id()); $current_forum_category = $forumEntity->getForumCategory(); $whatsnew_post_info = isset($_SESSION['whatsnew_post_info']) ? $_SESSION['whatsnew_post_info'] : null; if (api_is_in_gradebook()) { $interbreadcrumb[] = [ 'url' => Category::getUrl(), 'name' => get_lang('Assessments'), ]; } $groupId = api_get_group_id(); $group_properties = GroupManager::get_group_properties($groupId); $sessionId = api_get_session_id(); $ajaxURL = api_get_path(WEB_AJAX_PATH).'forum.ajax.php?'.api_get_cidreq().'&a=change_post_status'; $htmlHeadXtra[] = ''; /* Actions */ $my_action = isset($_GET['action']) ? $_GET['action'] : ''; $logInfo = [ 'tool' => TOOL_FORUM, 'tool_id' => $forumId, 'tool_id_detail' => $threadId, 'action' => !empty($my_action) ? $my_action : 'view-thread', 'action_details' => isset($_GET['content']) ? $_GET['content'] : '', ]; Event::registerLog($logInfo); $currentUrl = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?forum='.$forumId.'&'.api_get_cidreq().'&thread='.$threadId; switch ($my_action) { case 'delete_attach': delete_attachment($_GET['post'], $_GET['id_attach']); header('Location: '.$currentUrl); exit; break; case 'delete': if ( isset($_GET['content']) && isset($_GET['id']) && (api_is_allowed_to_edit(false, true) || (isset($group_properties['iid']) && GroupManager::is_tutor_of_group(api_get_user_id(), $group_properties))) ) { /** @var CForumPost $postEntity */ $postEntity = $repoPost->find($_GET['id']); deletePost($postEntity); } header('Location: '.$currentUrl); exit; break; case 'invisible': case 'visible': if (isset($_GET['id']) && (api_is_allowed_to_edit(false, true) || (isset($group_properties['iid']) && GroupManager::is_tutor_of_group(api_get_user_id(), $group_properties))) ) { /** @var CForumPost $postEntity */ $postEntity = $repoPost->find($_GET['id']); $message = approvePost($postEntity, $_GET['action']); Display::addFlash(Display::return_message(get_lang($message))); } header('Location: '.$currentUrl); exit; break; case 'move': if (isset($_GET['post'])) { $form = move_post_form(); // Validation or display if ($form->validate()) { $values = $form->exportValues(); store_move_post($values); $currentUrl = api_get_path(WEB_CODE_PATH). 'forum/viewthread.php?forum='.$forumId.'&'.api_get_cidreq().'&thread='.$threadId; header('Location: '.$currentUrl); exit; } else { $moveForm = $form->returnForm(); } } break; case 'report': $result = reportPost($postEntity, $forumEntity, $threadEntity); Display::addFlash(Display::return_message(get_lang('Reported'))); header('Location: '.$currentUrl); exit; break; case 'ask_revision': if (api_get_configuration_value('allow_forum_post_revisions')) { $result = savePostRevision($postEntity); Display::addFlash(Display::return_message(get_lang('Saved.'))); } header('Location: '.$currentUrl); exit; break; } if (!empty($groupId)) { $interbreadcrumb[] = [ 'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(), 'name' => get_lang('Groups'), ]; $interbreadcrumb[] = [ 'url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(), 'name' => get_lang('Group area').' '.$group_properties['name'], ]; $interbreadcrumb[] = [ 'url' => api_get_path(WEB_CODE_PATH).'forum/viewforum.php?forum='.$forumId.'&'.api_get_cidreq().'&search='.Security::remove_XSS(urlencode($my_search)), 'name' => Security::remove_XSS($forumEntity->getForumTitle()), ]; $interbreadcrumb[] = [ 'url' => api_get_path(WEB_CODE_PATH).'forum/viewthread.php?forum='.$forumId.'&'.api_get_cidreq().'&thread='.$threadId, 'name' => Security::remove_XSS($threadEntity->getThreadTitle()), ]; } else { $my_search = isset($_GET['search']) ? $_GET['search'] : ''; if ('learnpath' != $origin) { $interbreadcrumb[] = [ 'url' => api_get_path(WEB_CODE_PATH).'forum/index.php?'.api_get_cidreq().'&search='.Security::remove_XSS( urlencode($my_search) ), 'name' => $nameTools, ]; $interbreadcrumb[] = [ 'url' => api_get_path( WEB_CODE_PATH ).'forum/viewforumcategory.php?forumcategory='.$current_forum_category->getIid().'&search='.Security::remove_XSS( urlencode($my_search) ), 'name' => Security::remove_XSS($current_forum_category->getCatTitle()), ]; $interbreadcrumb[] = [ 'url' => api_get_path(WEB_CODE_PATH).'forum/viewforum.php?'.api_get_cidreq().'&forum='.$forumId.'&search='.Security::remove_XSS(urlencode($my_search)), 'name' => Security::remove_XSS($forumEntity->getForumTitle()), ]; $interbreadcrumb[] = [ 'url' => '#', 'name' => Security::remove_XSS($threadEntity->getThreadTitle()), ]; } } // If the user is not a course administrator and the forum is hidden // then the user is not allowed here. if (!api_is_allowed_to_edit(false, true) && (!$forumEntity->isVisible($courseEntity, $sessionEntity) || !$threadEntity->isVisible($courseEntity, $sessionEntity)) ) { api_not_allowed(); } // this increases the number of times the thread has been viewed increase_thread_view($threadId); if ('learnpath' == $origin) { $template = new Template('', false, false, true, true, false); } else { $template = new Template(); } $actions = ''.search_link().''; if ('learnpath' != $origin) { $actions .= '' .Display::return_icon('back.png', get_lang('Back to forum'), '', ICON_SIZE_MEDIUM).''; } // The reply to thread link should only appear when the forum_category is // not locked AND the forum is not locked AND the thread is not locked. // If one of the three levels is locked then the link should not be displayed. if (($current_forum_category && 0 == $current_forum_category->getLocked()) && 0 == $forumEntity->getLocked() && 0 == $threadEntity->getLocked() || api_is_allowed_to_edit(false, true) ) { // The link should only appear when the user is logged in or when anonymous posts are allowed. if ($_user['user_id'] || (1 == $forumEntity->getAllowAnonymous() && !$_user['user_id'])) { // reply link if (!api_is_anonymous() && api_is_allowed_to_session_edit(false, true)) { $actions .= '' .Display::return_icon('reply_thread.png', get_lang('Reply to this thread'), '', ICON_SIZE_MEDIUM) .''; } // new thread link if (( api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && $forumEntity->getSessionId() != $sessionId)) || (1 == $forumEntity->getAllowNewThreads() && isset($_user['user_id'])) || (1 == $forumEntity->getAllowNewThreads() && !isset($_user['user_id']) && 1 == $forumEntity->getAllowAnonymous()) ) { if (1 != $forumEntity->getLocked() && 1 != $forumEntity->getLocked()) { $actions .= '  '; } else { $actions .= get_lang('Forum blocked'); } } } } $template->assign('forum_actions', $actions); $template->assign('origin', api_get_origin()); /* Display Forum Category and the Forum information */ if (!isset($_SESSION['view'])) { $viewMode = $forumEntity->getDefaultView(); } else { $viewMode = $_SESSION['view']; } $whiteList = ['flat', 'threaded', 'nested']; if (isset($_GET['view']) && in_array($_GET['view'], $whiteList)) { $viewMode = $_GET['view']; $_SESSION['view'] = $viewMode; } if (empty($viewMode)) { $viewMode = 'flat'; } if ($threadEntity->isThreadPeerQualify()) { Display::addFlash(Display::return_message(get_lang('To get the expected score in this forum, your contribution will have to be scored by another student, and you will have to score at least 2 other student\'s contributions. Until you reach this objective, even if scored, your contribution will show as a 0 score in the global grades for this course.'), 'info')); } $allowReport = reportAvailable(); $origin = api_get_origin(); $sessionId = api_get_session_id(); $_user = api_get_user_info(); $userId = api_get_user_id(); $groupId = api_get_group_id(); // Decide whether we show the latest post first $sortDirection = isset($_GET['posts_order']) && 'desc' === $_GET['posts_order'] ? 'DESC' : ('learnpath' != $origin ? 'ASC' : 'DESC'); $posts = getPosts($forumEntity, $threadId, $sortDirection, true); $count = 0; $group_id = api_get_group_id(); $locked = api_resource_is_locked_by_gradebook($threadId, LINK_FORUM_THREAD); $sessionId = api_get_session_id(); $userId = api_get_user_id(); $groupInfo = GroupManager::get_group_properties($group_id); $postCount = 1; $allowUserImageForum = api_get_course_setting('allow_user_image_forum'); // The user who posted it can edit his thread only if the course admin allowed this in the properties // of the forum // The course admin him/herself can do this off course always $tutorGroup = GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo); $postList = []; foreach ($posts as $post) { /** @var CForumPost $postEntity */ $postEntity = $post['entity']; $posterId = isset($post['user_id']) ? $post['user_id'] : 0; $username = ''; if (isset($post['username'])) { $username = sprintf(get_lang('Login: %s'), $post['username']); } $name = $post['complete_name']; if (empty($posterId)) { $name = $post['poster_name']; } $post['user_data'] = ''; if ('learnpath' != $origin) { if ($allowUserImageForum) { $post['user_data'] = '
'. display_user_image($posterId, $name, $origin).'
'; } $post['user_data'] .= Display::tag( 'h4', display_user_link($posterId, $name, $origin, $username), ['class' => 'title-username'] ); $_user = api_get_user_info($posterId); $iconStatus = $_user['icon_status']; $post['user_data'] .= '
'.$iconStatus.'
'; } else { if ($allowUserImageForum) { $post['user_data'] .= '
'. display_user_image($posterId, $name, $origin).'
'; } $post['user_data'] .= Display::tag( 'p', $name, [ 'title' => api_htmlentities($username, ENT_QUOTES), 'class' => 'lead', ] ); } if ('learnpath' !== $origin) { $post['user_data'] .= Display::tag( 'p', Display::dateToStringAgoAndLongDate($post['post_date']), ['class' => 'post-date'] ); } else { $post['user_data'] .= Display::tag( 'p', Display::dateToStringAgoAndLongDate($post['post_date']), ['class' => 'text-muted'] ); } // get attach id $attachment_list = get_attachment($post['post_id']); $id_attach = !empty($attachment_list) ? $attachment_list['iid'] : ''; $iconEdit = ''; $editButton = ''; $askForRevision = ''; if ((isset($groupInfo['iid']) && $tutorGroup) || (1 == $forumEntity->getAllowEdit() && $posterId == $userId) || (api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && $forumEntity->getSessionId() != $sessionId)) ) { if (false == $locked && postIsEditableByStudent($forumEntity, $post)) { $editUrl = api_get_path(WEB_CODE_PATH).'forum/editpost.php?'.api_get_cidreq(); $editUrl .= "&forum=$forumId&thread=$threadId&post={$post['post_id']}&id_attach=$id_attach"; $iconEdit .= "" .Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL) .''; $editButton = Display::toolbarButton( get_lang('Edit'), $editUrl, 'pencil', 'default' ); } } if ((isset($groupInfo['iid']) && $tutorGroup) || api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && $forumEntity->getSessionId() != $sessionId) ) { if (false == $locked) { $deleteUrl = api_get_self().'?'.api_get_cidreq().'&'.http_build_query( [ 'forum' => $forumId, 'thread' => $threadId, 'action' => 'delete', 'content' => 'post', 'id' => $post['post_id'], ] ); $iconEdit .= Display::url( Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL), $deleteUrl, [ 'onclick' => "javascript:if(!confirm('" .addslashes(api_htmlentities(get_lang('Are you sure you want to delete this post? Deleting this post will also delete the replies on this post. Please check the threaded view to see which posts will also be deleted'), ENT_QUOTES)) ."')) return false;", 'id' => "delete-post-{$post['post_id']}", ] ); } } if (api_is_allowed_to_edit(false, true) && !( api_is_session_general_coach() && $forumEntity->getSessionId() != $sessionId ) ) { $iconEdit .= return_visible_invisible_icon( 'post', $post['post_id'], $post['visible'], [ 'forum' => $forumId, 'thread' => $threadId, ] ); if ($count > 0) { $iconEdit .= ''.Display::return_icon('move.png', get_lang('Move post'), [], ICON_SIZE_SMALL).''; } } $userCanQualify = 1 == $threadEntity->isThreadPeerQualify() && $post['poster_id'] != $userId; if (api_is_allowed_to_edit(null, true)) { $userCanQualify = true; } $postIsARevision = false; $flagRevision = ''; if ($post['poster_id'] == $userId) { $revision = getPostRevision($post['post_id']); if (empty($revision)) { $askForRevision = getAskRevisionButton($postEntity, $threadEntity); } else { $postIsARevision = true; $languageId = api_get_language_id(strtolower($revision)); $languageInfo = api_get_language_info($languageId); if ($languageInfo) { $languages = api_get_language_list_for_flag(); $flagRevision = ' '; } } } else { if (postNeedsRevision($postEntity)) { $askForRevision = giveRevisionButton($post['post_id'], $threadEntity); } else { $revision = getPostRevision($post['post_id']); if (!empty($revision)) { $postIsARevision = true; $languageId = api_get_language_id(strtolower($revision)); $languageInfo = api_get_language_info($languageId); if ($languageInfo) { $languages = api_get_language_list_for_flag(); $flagRevision = ' '; } } } } $post['is_a_revision'] = $postIsARevision; $post['flag_revision'] = $flagRevision; if (empty($threadEntity->getThreadQualifyMax())) { $userCanQualify = false; } if ($userCanQualify) { if ($count > 0) { $current_qualify_thread = showQualify( '1', $posterId, $threadId ); if (false == $locked) { $iconEdit .= ''.Display::return_icon('quiz.png', get_lang('Grade activity')).''; } } } $reportButton = ''; if ($allowReport) { $reportButton = getReportButton($post['post_id'], $threadEntity); } $statusIcon = getPostStatus($forumEntity, $post); if (!empty($iconEdit)) { $post['user_data'] .= "
$iconEdit $statusIcon
"; } else { if (!empty(strip_tags($statusIcon))) { $post['user_data'] .= "
$statusIcon
"; } } $buttonReply = ''; $buttonQuote = ''; $waitingValidation = ''; if (($current_forum_category && 0 == $current_forum_category->getLocked()) && 0 == $forumEntity->getLocked() && 0 == $threadEntity->getLocked() || api_is_allowed_to_edit(false, true) ) { if ($userId || (1 == $forumEntity->getAllowAnonymous() && !$userId)) { if (!api_is_anonymous() && api_is_allowed_to_session_edit(false, true)) { $buttonReply = Display::toolbarButton( get_lang('Reply to this message'), 'reply.php?'.api_get_cidreq().'&'.http_build_query([ 'forum' => $forumId, 'thread' => $threadId, 'post' => $post['post_id'], 'action' => 'replymessage', ]), 'reply', 'primary', ['id' => "reply-to-post-{$post['post_id']}"] ); $buttonQuote = Display::toolbarButton( get_lang('Quote this message'), 'reply.php?'.api_get_cidreq().'&'.http_build_query([ 'forum' => $forumId, 'thread' => $threadId, 'post' => $post['post_id'], 'action' => 'quote', ]), 'quote-left', 'success', ['id' => "quote-post-{$post['post_id']}"] ); if ($forumEntity->isModerated() && !api_is_allowed_to_edit(false, true)) { if (empty($post['status']) || CForumPost::STATUS_WAITING_MODERATION == $post['status']) { $buttonReply = ''; $buttonQuote = ''; } } } } } else { $closedPost = ''; if ($current_forum_category && 1 == $current_forum_category->getLocked()) { $closedPost = Display::tag( 'div', ' '.get_lang('Forum category Locked'), ['class' => 'alert alert-warning post-closed'] ); } if (1 == $forumEntity->getLocked()) { $closedPost = Display::tag( 'div', ' '.get_lang('Forum blocked'), ['class' => 'alert alert-warning post-closed'] ); } if (1 == $threadEntity->getLocked()) { $closedPost = Display::tag( 'div', ' '.get_lang('Thread is locked.'), ['class' => 'alert alert-warning post-closed'] ); } $post['user_data'] .= $closedPost; } // note: this can be removed here because it will be displayed in the tree /*if (isset($whatsnew_post_info[$forumId][$threadId][$post['post_id']]) && !empty($whatsnew_post_info[$forumId][$threadId][$post['post_id']]) && !empty($whatsnew_post_info[$forumId][$post['thread_id']]) ) { $post_image = Display::return_icon('forumpostnew.gif'); } else { $post_image = Display::return_icon('forumpost.gif'); } if ('1' == $post['post_notification'] && $post['poster_id'] == $userId) { $post_image .= Display::return_icon( 'forumnotification.gif', get_lang('You will be notified') ); }*/ $post['current'] = false; if (isset($_GET['post_id']) && $_GET['post_id'] == $post['post_id']) { $post['current'] = true; } // Replace Re: with an icon $search = [ get_lang('Re:'), 'Re:', 'RE:', 'AW:', 'Aw:', ]; $replace = ''.Display::returnFontAwesomeIcon('mail-reply').''; $post['post_title'] = str_replace($search, $replace, Security::remove_XSS($post['post_title'])); // The post title $titlePost = Display::tag('h3', $post['post_title'], ['class' => 'forum_post_title']); $post['post_title'] = ''; $post['post_title'] .= Display::tag('div', $titlePost, ['class' => 'post-header']); // the post body $post['post_data'] = Display::tag('div', $post['post_text'], ['class' => 'post-body']); // The check if there is an attachment $post['post_attachments'] = ''; $attachments = $postEntity->getAttachments(); if ($attachments) { $repo = Container::getForumAttachmentRepository(); /** @var \Chamilo\CourseBundle\Entity\CForumAttachment $attachment */ foreach ($attachments as $attachment) { $post['post_attachments'] .= Display::return_icon('attachment.png', get_lang('Attachment')); $url = $repo->getResourceFileDownloadUrl($attachment); $post['post_attachments'] .= Display::url($attachment->getFilename(), $url); $post['post_attachments'] .= ''.$attachment->getComment().''; if ((1 == $forumEntity->getAllowEdit() && $post['user_id'] == $userId) || (api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && $forumEntity->getSessionId() != $sessionId)) ) { $post['post_attachments'] .= '  ' .Display::return_icon('delete.png', get_lang('Delete')).'
'; } } } $post['post_buttons'] = "$askForRevision $editButton $reportButton $buttonReply $buttonQuote $waitingValidation"; $postList[] = $post; // The post has been displayed => it can be removed from the what's new array //unset($whatsnew_post_info[$current_forum['forum_id']][$current_thread['thread_id']][$post['post_id']]); //unset($_SESSION['whatsnew_post_info'][$current_forum['forum_id']][$current_thread['thread_id']][$post['post_id']]); $count++; } $template->assign('posts', $postList); $formToString = ''; $showForm = true; if (!api_is_allowed_to_edit(false, true) && (($current_forum_category && 0 == !$current_forum_category->isVisible($courseEntity, $sessionEntity)) || !$forumEntity->isVisible($courseEntity, $sessionEntity)) ) { $showForm = false; } if (!api_is_allowed_to_edit(false, true) && ( ($current_forum_category && 0 != $current_forum_category->getLocked()) || 0 != $forumEntity->getLocked() || 0 != $threadEntity->getLocked() ) ) { $showForm = false; } if (!$_user['user_id'] && 0 == $forumEntity->getAllowAnonymous()) { $showForm = false; } if (0 != $forumEntity->getForumOfGroup()) { $show_forum = GroupManager::user_has_access( api_get_user_id(), $forumEntity->getForumOfGroup(), GroupManager::GROUP_TOOL_FORUM ); if (!$show_forum) { $showForm = false; } } if ($showForm) { $form = show_add_post_form( $forumEntity, $threadEntity, null, null, null ); $formToString = $form->returnForm(); } $template->assign('form', $formToString); $template->assign('move_form', $moveForm); $layout = $template->get_template('forum/posts.tpl'); $template->display($layout);