package org.iatoki.judgels.raguel.forum.thread.post;
import org.iatoki.judgels.api.jophiel.JophielClientAPI;
import org.iatoki.judgels.api.jophiel.JophielPublicAPI;
import org.iatoki.judgels.jophiel.avatar.BaseAvatarCacheService;
import org.iatoki.judgels.jophiel.activity.UserActivityMessageService;
import org.iatoki.judgels.play.Page;
import org.iatoki.judgels.play.jid.BaseJidCacheService;
import org.iatoki.judgels.play.template.HtmlTemplate;
import org.iatoki.judgels.raguel.forum.AbstractForumController;
import org.iatoki.judgels.raguel.forum.Forum;
import org.iatoki.judgels.raguel.forum.thread.ForumThread;
import org.iatoki.judgels.raguel.forum.thread.ForumThreadNotFoundException;
import org.iatoki.judgels.raguel.user.item.UserItemStatus;
import org.iatoki.judgels.raguel.controllers.securities.Authenticated;
import org.iatoki.judgels.raguel.controllers.securities.GuestView;
import org.iatoki.judgels.raguel.controllers.securities.HasRole;
import org.iatoki.judgels.raguel.controllers.securities.LoggedIn;
import org.iatoki.judgels.raguel.forum.module.ForumModules;
import org.iatoki.judgels.raguel.forum.member.ForumMemberService;
import org.iatoki.judgels.raguel.forum.thread.ForumThreadService;
import org.iatoki.judgels.raguel.user.item.UserItemService;
import org.iatoki.judgels.raguel.forum.thread.post.html.editThreadPostView;
import org.iatoki.judgels.raguel.forum.thread.post.html.listPostContentsView;
import org.iatoki.judgels.raguel.forum.thread.post.html.listThreadPostsTreeView;
import org.iatoki.judgels.raguel.forum.thread.post.html.listThreadPostsView;
import org.iatoki.judgels.raguel.forum.thread.post.html.replyThreadPostView;
import play.data.Form;
import play.db.jpa.Transactional;
import play.filters.csrf.AddCSRFToken;
import play.filters.csrf.RequireCSRFCheck;
import play.i18n.Messages;
import play.mvc.Result;
import play.twirl.api.Html;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Singleton
public final class ThreadPostController extends AbstractForumController {
private static final long PAGE_SIZE = 20;
private final ForumThreadService forumThreadService;
private final ThreadPostService threadPostService;
private final UserItemService userItemService;
@Inject
public ThreadPostController(BaseJidCacheService jidCacheService, BaseAvatarCacheService avatarCacheService, JophielClientAPI jophielClientAPI, JophielPublicAPI jophielPublicAPI, UserActivityMessageService userActivityMessageService, ForumMemberService forumMemberService, ForumThreadService forumThreadService, ThreadPostService threadPostService, UserItemService userItemService) {
super(jidCacheService, avatarCacheService, jophielClientAPI, jophielPublicAPI, userActivityMessageService, forumMemberService);
this.forumThreadService = forumThreadService;
this.threadPostService = threadPostService;
this.userItemService = userItemService;
}
@Authenticated(value = GuestView.class)
@Transactional
public Result viewThreadPosts(long forumThreadId) throws ForumThreadNotFoundException {
return showListThreadPosts(forumThreadId, 0, "id", "asc", "");
}
@Authenticated(value = GuestView.class)
@Transactional
public Result listThreadPosts(long forumThreadId, long pageIndex, String orderBy, String orderDir, String filterString) throws ForumThreadNotFoundException {
return showListThreadPosts(forumThreadId, pageIndex, orderBy, orderDir, filterString);
}
@Authenticated(value = GuestView.class)
@Transactional
public Result viewTreeThreadPosts(long forumThreadId) throws ForumThreadNotFoundException {
ForumThread forumThread = forumThreadService.findForumThreadById(forumThreadId);
Forum forum = forumThread.getParentForum();
if (!forum.containModule(ForumModules.THREAD)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!isCurrentUserAllowedToEnterForum(forum)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
List<ThreadPostWithLevel> threadPostsWithLevel = threadPostService.getAllThreadPostsWithLevel(forumThread);
List<String> replyJids = threadPostsWithLevel.stream().map(e -> e.getThreadPost().getReplyJid()).collect(Collectors.toList());
Map<String, Long> replyJidToIdMap = threadPostService.getThreadPostsJidToIdMap(replyJids);
Map<String, String> replyJidToUserJidMap = threadPostService.getThreadPostsJidToUserJidMap(replyJids);
userItemService.upsertUserItem(getCurrentUserJid(), forumThread.getJid(), UserItemStatus.VIEWED);
HtmlTemplate htmlTemplate = getBaseHtmlTemplate(forum);
Html content = listThreadPostsTreeView.render(forumThread, threadPostsWithLevel, replyJidToIdMap, replyJidToUserJidMap);
htmlTemplate.setContent(content);
htmlTemplate.setMainTitle(forumThread.getName());
htmlTemplate.setMainBackButton(Messages.get("commons.button.backTo1", forumThread.getParentForum().getName()), org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forumThread.getParentForum().getId()));
htmlTemplate.markBreadcrumbLocation(forumThread.getName(), routes.ThreadPostController.viewThreadPosts(forumThread.getId()));
return renderTemplate(htmlTemplate);
}
@Authenticated(value = GuestView.class)
@Transactional
public Result viewPostVersions(long threadPostId) throws ThreadPostNotFoundException {
ThreadPost threadPost = threadPostService.findThreadPostById(threadPostId);
Forum forum = threadPost.getThread().getParentForum();
if (!forum.containModule(ForumModules.THREAD)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!isCurrentUserAllowedToEnterForum(forum)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
HtmlTemplate htmlTemplate = getBaseHtmlTemplate(forum);
Html content = listPostContentsView.render(threadPost);
htmlTemplate.setContent(content);
htmlTemplate.setMainTitle(Messages.get("forum.thread.post.text.versions"));
htmlTemplate.setMainBackButton(Messages.get("commons.button.backTo1", threadPost.getThread().getName()), routes.ThreadPostController.viewThreadPosts(threadPost.getThread().getId()));
htmlTemplate.markBreadcrumbLocation(threadPost.getThread().getName(), routes.ThreadPostController.viewThreadPosts(threadPost.getThread().getId()));
return renderTemplate(htmlTemplate);
}
@Authenticated(value = {LoggedIn.class, HasRole.class})
@Transactional(readOnly = true)
@AddCSRFToken
public Result editThreadPost(long threadPostId) throws ThreadPostNotFoundException {
ThreadPost threadPost = threadPostService.findThreadPostById(threadPostId);
Forum forum = threadPost.getThread().getParentForum();
if (!forum.containModule(ForumModules.THREAD)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!isCurrentUserAllowedToEnterForum(forum)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!getCurrentUserJid().equals(threadPost.getUserJid())) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
ThreadPostUpsertForm threadPostUpsertData = new ThreadPostUpsertForm();
threadPostUpsertData.subject = threadPost.getLatestContent().getSubject();
threadPostUpsertData.content = threadPost.getLatestContent().getContent();
Form<ThreadPostUpsertForm> threadPostUpsertForm = Form.form(ThreadPostUpsertForm.class).fill(threadPostUpsertData);
return showEditThreadPost(threadPost, threadPostUpsertForm);
}
@Authenticated(value = {LoggedIn.class, HasRole.class})
@Transactional
@RequireCSRFCheck
public Result postEditThreadPost(long threadPostId) throws ThreadPostNotFoundException {
ThreadPost threadPost = threadPostService.findThreadPostById(threadPostId);
Forum forum = threadPost.getThread().getParentForum();
if (!forum.containModule(ForumModules.THREAD)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!isCurrentUserAllowedToEnterForum(forum)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!getCurrentUserJid().equals(threadPost.getUserJid())) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
Form<ThreadPostUpsertForm> threadPostUpsertForm = Form.form(ThreadPostUpsertForm.class).bindFromRequest();
if (formHasErrors(threadPostUpsertForm)) {
return showEditThreadPost(threadPost, threadPostUpsertForm);
}
ThreadPostUpsertForm threadPostUpsertData = threadPostUpsertForm.get();
threadPostService.editPost(threadPost, getCurrentUserJid(), threadPostUpsertData.subject, threadPostUpsertData.content, getCurrentUserIpAddress());
return redirect(routes.ThreadPostController.viewThreadPosts(threadPost.getThread().getId()));
}
@Authenticated(value = {LoggedIn.class, HasRole.class})
@Transactional(readOnly = true)
@AddCSRFToken
public Result replyThreadPost(long threadPostId) throws ThreadPostNotFoundException {
ThreadPost threadPost = threadPostService.findThreadPostById(threadPostId);
Forum forum = threadPost.getThread().getParentForum();
if (!forum.containModule(ForumModules.THREAD)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!isCurrentUserAllowedToEnterForum(forum)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
ThreadPostUpsertForm threadPostUpsertData = new ThreadPostUpsertForm();
if (threadPost.getReplyJid() == null) {
threadPostUpsertData.subject = "Re: " + threadPost.getLatestContent().getSubject();
} else {
threadPostUpsertData.subject = threadPost.getLatestContent().getSubject();
}
Form<ThreadPostUpsertForm> threadPostUpsertForm = Form.form(ThreadPostUpsertForm.class).fill(threadPostUpsertData);
return showReplyThreadPost(threadPost, threadPostUpsertForm);
}
@Authenticated(value = {LoggedIn.class, HasRole.class})
@Transactional
@RequireCSRFCheck
public Result postReplyThreadPost(long threadPostId) throws ThreadPostNotFoundException {
ThreadPost threadPost = threadPostService.findThreadPostById(threadPostId);
Forum forum = threadPost.getThread().getParentForum();
if (!forum.containModule(ForumModules.THREAD)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!isCurrentUserAllowedToEnterForum(forum)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
Form<ThreadPostUpsertForm> threadPostUpsertForm = Form.form(ThreadPostUpsertForm.class).bindFromRequest();
if (formHasErrors(threadPostUpsertForm)) {
return showReplyThreadPost(threadPost, threadPostUpsertForm);
}
ThreadPostUpsertForm threadPostUpsertData = threadPostUpsertForm.get();
threadPostService.replyPost(threadPost, getCurrentUserJid(), threadPostUpsertData.subject, threadPostUpsertData.content, getCurrentUserIpAddress());
long totalPost = threadPostService.countThreadPost(threadPost.getThread());
return redirect(routes.ThreadPostController.listThreadPosts(threadPost.getThread().getId(), ((totalPost - 1) / PAGE_SIZE), "id", "asc", ""));
}
@Override
protected HtmlTemplate getBaseHtmlTemplate(Forum forum) {
HtmlTemplate htmlTemplate = super.getBaseHtmlTemplate();
markForumBreadcrumbs(htmlTemplate, forum);
return htmlTemplate;
}
private Result showListThreadPosts(long forumThreadId, long pageIndex, String orderBy, String orderDir, String filterString) throws ForumThreadNotFoundException {
ForumThread forumThread = forumThreadService.findForumThreadById(forumThreadId);
Forum forum = forumThread.getParentForum();
if (!forum.containModule(ForumModules.THREAD)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
if (!isCurrentUserAllowedToEnterForum(forum)) {
return redirect(org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forum.getId()));
}
Page<ThreadPost> pageOfThreadPosts = threadPostService.getPageOfThreadPosts(forumThread, pageIndex, PAGE_SIZE, orderBy, orderDir, filterString);
List<String> replyJids = pageOfThreadPosts.getData().stream().map(e -> e.getReplyJid()).collect(Collectors.toList());
Map<String, Long> replyJidToIdMap = threadPostService.getThreadPostsJidToIdMap(replyJids);
Map<String, String> replyJidToUserJidMap = threadPostService.getThreadPostsJidToUserJidMap(replyJids);
userItemService.upsertUserItem(getCurrentUserJid(), forumThread.getJid(), UserItemStatus.VIEWED);
HtmlTemplate htmlTemplate = getBaseHtmlTemplate(forum);
Html content = listThreadPostsView.render(forumThread, pageOfThreadPosts, replyJidToIdMap, replyJidToUserJidMap, orderBy, orderDir, filterString);
htmlTemplate.setContent(content);
htmlTemplate.setMainTitle(forumThread.getName());
htmlTemplate.setMainBackButton(Messages.get("commons.button.backTo1", forumThread.getParentForum().getName()), org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(forumThread.getParentForum().getId()));
htmlTemplate.markBreadcrumbLocation(forumThread.getName(), routes.ThreadPostController.viewThreadPosts(forumThread.getId()));
return renderTemplate(htmlTemplate);
}
private Result showEditThreadPost(ThreadPost threadPost, Form<ThreadPostUpsertForm> threadPostUpsertForm) {
HtmlTemplate htmlTemplate = getBaseHtmlTemplate(threadPost.getThread().getParentForum());
Html content = editThreadPostView.render(threadPost, threadPostUpsertForm);
htmlTemplate.setContent(content);
htmlTemplate.setMainTitle(Messages.get("commons.button.edit"));
htmlTemplate.setMainBackButton(Messages.get("commons.button.backTo1", threadPost.getThread().getParentForum().getName()), org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(threadPost.getThread().getParentForum().getId()));
htmlTemplate.markBreadcrumbLocation(threadPost.getThread().getName(), routes.ThreadPostController.viewThreadPosts(threadPost.getThread().getId()));
htmlTemplate.markBreadcrumbLocation(Messages.get("commons.button.edit"), routes.ThreadPostController.editThreadPost(threadPost.getId()));
return renderTemplate(htmlTemplate);
}
private Result showReplyThreadPost(ThreadPost threadPost, Form<ThreadPostUpsertForm> threadPostUpsertForm) {
HtmlTemplate htmlTemplate = getBaseHtmlTemplate(threadPost.getThread().getParentForum());
Html content = replyThreadPostView.render(threadPost, threadPostUpsertForm);
htmlTemplate.setContent(content);
htmlTemplate.setMainTitle(Messages.get("forum.thread.post.text.reply"));
htmlTemplate.setMainBackButton(Messages.get("commons.button.backTo1", threadPost.getThread().getParentForum().getName()), org.iatoki.judgels.raguel.forum.routes.ForumController.viewForums(threadPost.getThread().getParentForum().getId()));
htmlTemplate.markBreadcrumbLocation(threadPost.getThread().getName(), routes.ThreadPostController.viewThreadPosts(threadPost.getThread().getId()));
htmlTemplate.markBreadcrumbLocation(Messages.get("forum.thread.post.text.reply"), routes.ThreadPostController.replyThreadPost(threadPost.getId()));
return renderTemplate(htmlTemplate);
}
}