discussion/app/controllers/CommentsController.scala (95 lines of code) (raw):

package controllers import common.{ImplicitControllerExecutionContext, JsonComponent} import discussion.api.DiscussionApiException._ import discussion.api.{DiscussionApiLike, DiscussionParams} import discussion.model.{BlankComment, DiscussionAbuseReport, DiscussionKey} import discussion.{ThreadedCommentPage, UnthreadedCommentPage} import model.Cached.RevalidatableResult import model._ import play.api.data.Forms._ import play.api.data._ import play.api.data.validation._ import play.api.mvc._ import play.filters.csrf.{CSRFAddToken, CSRFCheck} import scala.concurrent.Future import scala.util.control.NonFatal class CommentsController( val discussionApi: DiscussionApiLike, csrfCheck: CSRFCheck, csrfAddToken: CSRFAddToken, val controllerComponents: ControllerComponents, )(implicit context: ApplicationContext) extends DiscussionController with ImplicitControllerExecutionContext { // Used for jump to comment, comment hash location. def commentContextJson(id: Int): Action[AnyContent] = Action.async { implicit request => val params = DiscussionParams(request) discussionApi.commentContext(id, params) flatMap { context => getComments(context._1, Some(params.copy(page = context._2))) } recover toResult } def commentContextJsonOptions(id: Int): Action[AnyContent] = Action { implicit request => TinyResponse.noContent(Some("GET, OPTIONS")) } // Used for getting more replies for a specific comment. def commentJson(id: Int): Action[AnyContent] = comment(id) def comment(id: Int): Action[AnyContent] = Action.async { implicit request => discussionApi.commentFor(id, request.getQueryString("displayThreaded")) map { comment => Cached(CacheTime.DiscussionDefault) { if (request.isJson) JsonComponent(views.html.fragments.comment(comment, comment.discussion.isClosedForRecommendation)) else RevalidatableResult.Ok(views.html.fragments.comment(comment, comment.discussion.isClosedForRecommendation)) } } recover toResult } // Get a list of comments for a discussion. def comments(key: DiscussionKey): Action[AnyContent] = Action.async { implicit request => getComments(key) } def commentsJson(key: DiscussionKey): Action[AnyContent] = Action.async { implicit request => getComments(key) } def commentsJsonOptions(key: DiscussionKey): Action[AnyContent] = Action { implicit request => TinyResponse.noContent(Some("GET, OPTIONS")) } // Get the top comments for a discussion. def topCommentsJson(key: DiscussionKey): Action[AnyContent] = Action.async { implicit request => getTopComments(key) } def topCommentsJsonOptions(key: DiscussionKey): Action[AnyContent] = Action { implicit request => TinyResponse.noContent(Some("GET, OPTIONS")) } private def getComments(key: DiscussionKey, optParams: Option[DiscussionParams] = None)(implicit request: RequestHeader, ): Future[Result] = { val params = optParams.getOrElse(DiscussionParams(request)) discussionApi.commentsFor(key, params).map { comments => val page = if (params.displayThreaded) { ThreadedCommentPage(comments) } else { UnthreadedCommentPage(comments) } Cached(cacheTime(request)) { if (request.isJson) { JsonComponent( "commentsHtml" -> views.html.discussionComments.commentsList(page, renderPagination = false).toString, "paginationHtml" -> views.html.fragments.commentPagination(page).toString, "postedCommentHtml" -> views.html.fragments.comment(BlankComment()).toString, "lastPage" -> comments.pagination.lastPage, "commentCount" -> comments.commentCount, ) } else { RevalidatableResult.Ok(views.html.discussionComments.discussionPage(page)) } } } recover toResult } private def getTopComments(key: DiscussionKey)(implicit request: RequestHeader): Future[Result] = { discussionApi.commentsFor(key, DiscussionParams(topComments = true)).map { comments => val page = UnthreadedCommentPage(comments) Cached(cacheTime(request)) { if (request.isJson) { JsonComponent(views.html.discussionComments.topCommentsList(page)) } else { RevalidatableResult.Ok(views.html.discussionComments.topCommentsList(page)) } } } recover toResult } // caches "closed" comment threads for an hour. // if the thread is switched on again the url changes and it cache busts itself. private def cacheTime(request: RequestHeader) = { val commentsClosed = request.getParameter("commentsClosed").contains("true") if (commentsClosed) CacheTime.DiscussionClosed else CacheTime.DiscussionDefault } }