feat(community): 게시물 댓글 조회 포트를 구현한다
This commit is contained in:
@@ -12,6 +12,8 @@ import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreat
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.like.QCreatorCommunityLike.creatorCommunityLike
|
||||
import kr.co.vividnext.sodalive.member.QMember.member
|
||||
import kr.co.vividnext.sodalive.member.block.QBlockMember
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.port.out.CreatorChannelCommunityCommentContextRecord
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.port.out.CreatorChannelCommunityCommentRecord
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.port.out.CreatorChannelCommunityCreatorRecord
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.community.port.out.CreatorChannelCommunityPostRecord
|
||||
import org.springframework.stereotype.Repository
|
||||
@@ -119,6 +121,122 @@ class DefaultCreatorChannelCommunityQueryRepository(
|
||||
return rows.toCommunityPostRecords(creatorId, viewerId)
|
||||
}
|
||||
|
||||
override fun findCommunityPost(
|
||||
postId: Long,
|
||||
viewerId: Long,
|
||||
canViewAdultContent: Boolean
|
||||
): CreatorChannelCommunityPostRecord? {
|
||||
val rows = queryFactory
|
||||
.selectCommunityPostRow()
|
||||
.from(creatorCommunity)
|
||||
.where(communityPostByIdCondition(postId, canViewAdultContent))
|
||||
.fetch()
|
||||
|
||||
val creatorId = rows.firstOrNull()?.creatorId ?: return null
|
||||
return rows.toCommunityPostRecords(creatorId, viewerId).firstOrNull()
|
||||
}
|
||||
|
||||
override fun countCommunityComments(
|
||||
postId: Long,
|
||||
viewerId: Long,
|
||||
creatorId: Long
|
||||
): Int {
|
||||
return queryFactory
|
||||
.select(creatorCommunityComment.id.count())
|
||||
.from(creatorCommunityComment)
|
||||
.where(rootCommentCondition(postId, creatorId, viewerId))
|
||||
.fetchOne()
|
||||
?.toInt()
|
||||
?: 0
|
||||
}
|
||||
|
||||
override fun findCommunityComments(
|
||||
postId: Long,
|
||||
viewerId: Long,
|
||||
creatorId: Long,
|
||||
offset: Long,
|
||||
limit: Int
|
||||
): List<CreatorChannelCommunityCommentRecord> {
|
||||
return queryFactory
|
||||
.selectCommunityCommentRow()
|
||||
.from(creatorCommunityComment)
|
||||
.where(rootCommentCondition(postId, creatorId, viewerId))
|
||||
.orderBy(creatorCommunityComment.createdAt.desc(), creatorCommunityComment.id.desc())
|
||||
.offset(offset)
|
||||
.limit(limit.toLong())
|
||||
.fetch()
|
||||
.map { it.toCommunityCommentRecord() }
|
||||
}
|
||||
|
||||
override fun findLatestRepliesByCommentIds(
|
||||
commentIds: List<Long>,
|
||||
viewerId: Long
|
||||
): List<CreatorChannelCommunityCommentRecord> {
|
||||
if (commentIds.isEmpty()) return emptyList()
|
||||
|
||||
return queryFactory
|
||||
.selectCommunityCommentRow()
|
||||
.from(creatorCommunityComment)
|
||||
.where(replyCondition(commentIds, viewerId))
|
||||
.orderBy(creatorCommunityComment.createdAt.desc(), creatorCommunityComment.id.desc())
|
||||
.fetch()
|
||||
.map { it.toCommunityCommentRecord() }
|
||||
.groupBy { it.parentCommentId }
|
||||
.values
|
||||
.map { it.first() }
|
||||
}
|
||||
|
||||
override fun findRootCommentContext(
|
||||
commentId: Long,
|
||||
viewerId: Long,
|
||||
canViewAdultContent: Boolean
|
||||
): CreatorChannelCommunityCommentContextRecord? {
|
||||
val row = queryFactory
|
||||
.select(
|
||||
creatorCommunityComment.id,
|
||||
creatorCommunityComment.creatorCommunity.id,
|
||||
creatorCommunityComment.creatorCommunity.member.id,
|
||||
creatorCommunityComment.creatorCommunity.isCommentAvailable
|
||||
)
|
||||
.from(creatorCommunityComment)
|
||||
.where(rootCommentContextCondition(commentId, viewerId, canViewAdultContent))
|
||||
.fetchFirst() ?: return null
|
||||
|
||||
return CreatorChannelCommunityCommentContextRecord(
|
||||
commentId = row.get(creatorCommunityComment.id)!!,
|
||||
postId = row.get(creatorCommunityComment.creatorCommunity.id)!!,
|
||||
creatorId = row.get(creatorCommunityComment.creatorCommunity.member.id)!!,
|
||||
isCommentAvailable = row.get(creatorCommunityComment.creatorCommunity.isCommentAvailable)!!
|
||||
)
|
||||
}
|
||||
|
||||
override fun countCommunityReplies(commentId: Long, viewerId: Long): Int {
|
||||
return queryFactory
|
||||
.select(creatorCommunityComment.id.count())
|
||||
.from(creatorCommunityComment)
|
||||
.where(replyCondition(commentId, viewerId))
|
||||
.fetchOne()
|
||||
?.toInt()
|
||||
?: 0
|
||||
}
|
||||
|
||||
override fun findCommunityReplies(
|
||||
commentId: Long,
|
||||
viewerId: Long,
|
||||
offset: Long,
|
||||
limit: Int
|
||||
): List<CreatorChannelCommunityCommentRecord> {
|
||||
return queryFactory
|
||||
.selectCommunityCommentRow()
|
||||
.from(creatorCommunityComment)
|
||||
.where(replyCondition(commentId, viewerId))
|
||||
.orderBy(creatorCommunityComment.createdAt.desc(), creatorCommunityComment.id.desc())
|
||||
.offset(offset)
|
||||
.limit(limit.toLong())
|
||||
.fetch()
|
||||
.map { it.toCommunityCommentRecord() }
|
||||
}
|
||||
|
||||
private fun JPAQueryFactory.selectCommunityPostRow() = select(
|
||||
creatorCommunity.id,
|
||||
creatorCommunity.member.id,
|
||||
@@ -134,6 +252,17 @@ class DefaultCreatorChannelCommunityQueryRepository(
|
||||
creatorCommunity.isCommentAvailable
|
||||
)
|
||||
|
||||
private fun JPAQueryFactory.selectCommunityCommentRow() = select(
|
||||
creatorCommunityComment.id,
|
||||
creatorCommunityComment.parent.id,
|
||||
creatorCommunityComment.creatorCommunity.id,
|
||||
creatorCommunityComment.member.id,
|
||||
creatorCommunityComment.member.profileImage,
|
||||
creatorCommunityComment.member.nickname,
|
||||
creatorCommunityComment.comment,
|
||||
creatorCommunityComment.createdAt
|
||||
)
|
||||
|
||||
private fun communityPostCondition(creatorId: Long, canViewAdultContent: Boolean): BooleanExpression {
|
||||
val condition = creatorCommunity.isActive.isTrue
|
||||
.and(creatorCommunity.member.id.eq(creatorId))
|
||||
@@ -142,6 +271,62 @@ class DefaultCreatorChannelCommunityQueryRepository(
|
||||
return if (canViewAdultContent) condition else condition.and(creatorCommunity.isAdult.isFalse)
|
||||
}
|
||||
|
||||
private fun communityPostByIdCondition(postId: Long, canViewAdultContent: Boolean): BooleanExpression {
|
||||
val condition = creatorCommunity.id.eq(postId)
|
||||
.and(creatorCommunity.isActive.isTrue)
|
||||
.and(creatorCommunity.member.isActive.isTrue)
|
||||
|
||||
return if (canViewAdultContent) condition else condition.and(creatorCommunity.isAdult.isFalse)
|
||||
}
|
||||
|
||||
private fun rootCommentCondition(
|
||||
postId: Long,
|
||||
creatorId: Long,
|
||||
viewerId: Long
|
||||
): BooleanExpression {
|
||||
return creatorCommunityComment.creatorCommunity.id.eq(postId)
|
||||
.and(creatorCommunityComment.isActive.isTrue)
|
||||
.and(creatorCommunityComment.parent.isNull)
|
||||
.and(visibleSecretCommentCondition(creatorId, viewerId))
|
||||
.and(notBlockedCommentWriterCondition(viewerId))
|
||||
}
|
||||
|
||||
private fun rootCommentContextCondition(
|
||||
commentId: Long,
|
||||
viewerId: Long,
|
||||
canViewAdultContent: Boolean
|
||||
): BooleanExpression {
|
||||
val condition = creatorCommunityComment.id.eq(commentId)
|
||||
.and(creatorCommunityComment.isActive.isTrue)
|
||||
.and(creatorCommunityComment.parent.isNull)
|
||||
.and(creatorCommunityComment.creatorCommunity.isActive.isTrue)
|
||||
.and(creatorCommunityComment.creatorCommunity.member.isActive.isTrue)
|
||||
.and(
|
||||
creatorCommunityComment.isSecret.isFalse
|
||||
.or(creatorCommunityComment.creatorCommunity.member.id.eq(viewerId))
|
||||
.or(creatorCommunityComment.member.id.eq(viewerId))
|
||||
)
|
||||
.and(notBlockedCommentWriterCondition(viewerId))
|
||||
|
||||
return if (canViewAdultContent) condition else condition.and(creatorCommunityComment.creatorCommunity.isAdult.isFalse)
|
||||
}
|
||||
|
||||
private fun replyCondition(commentId: Long, viewerId: Long): BooleanExpression {
|
||||
return creatorCommunityComment.isActive.isTrue
|
||||
.and(creatorCommunityComment.parent.isNotNull)
|
||||
.and(creatorCommunityComment.parent.id.eq(commentId))
|
||||
.and(visibleSecretReplyCondition(viewerId))
|
||||
.and(notBlockedCommentWriterCondition(viewerId))
|
||||
}
|
||||
|
||||
private fun replyCondition(commentIds: List<Long>, viewerId: Long): BooleanExpression {
|
||||
return creatorCommunityComment.isActive.isTrue
|
||||
.and(creatorCommunityComment.parent.isNotNull)
|
||||
.and(creatorCommunityComment.parent.id.`in`(commentIds))
|
||||
.and(visibleSecretReplyCondition(viewerId))
|
||||
.and(notBlockedCommentWriterCondition(viewerId))
|
||||
}
|
||||
|
||||
private fun homeCommunityPostCondition(
|
||||
creatorId: Long,
|
||||
viewerId: Long,
|
||||
@@ -302,6 +487,12 @@ class DefaultCreatorChannelCommunityQueryRepository(
|
||||
.or(creatorCommunityComment.member.id.eq(viewerId))
|
||||
}
|
||||
|
||||
private fun visibleSecretReplyCondition(viewerId: Long): BooleanExpression {
|
||||
return creatorCommunityComment.isSecret.isFalse
|
||||
.or(creatorCommunityComment.creatorCommunity.member.id.eq(viewerId))
|
||||
.or(creatorCommunityComment.member.id.eq(viewerId))
|
||||
}
|
||||
|
||||
private fun notBlockedCommentWriterCondition(viewerId: Long): BooleanExpression {
|
||||
val viewerBlock = QBlockMember("communityCommentViewerBlockWriter")
|
||||
val writerBlock = QBlockMember("communityCommentWriterBlockViewer")
|
||||
@@ -355,4 +546,17 @@ class DefaultCreatorChannelCommunityQueryRepository(
|
||||
|
||||
private val Tuple.isCommentAvailable: Boolean
|
||||
get() = get(creatorCommunity.isCommentAvailable)!!
|
||||
|
||||
private fun Tuple.toCommunityCommentRecord(): CreatorChannelCommunityCommentRecord {
|
||||
return CreatorChannelCommunityCommentRecord(
|
||||
commentId = get(creatorCommunityComment.id)!!,
|
||||
parentCommentId = get(creatorCommunityComment.parent.id),
|
||||
postId = get(creatorCommunityComment.creatorCommunity.id)!!,
|
||||
writerId = get(creatorCommunityComment.member.id)!!,
|
||||
writerProfilePath = get(creatorCommunityComment.member.profileImage),
|
||||
writerNickname = get(creatorCommunityComment.member.nickname)!!,
|
||||
content = get(creatorCommunityComment.comment)!!,
|
||||
createdAt = get(creatorCommunityComment.createdAt)!!
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,49 @@ interface CreatorChannelCommunityQueryPort {
|
||||
canViewAdultContent: Boolean,
|
||||
limit: Int
|
||||
): List<CreatorChannelCommunityPostRecord>
|
||||
|
||||
fun findCommunityPost(
|
||||
postId: Long,
|
||||
viewerId: Long,
|
||||
canViewAdultContent: Boolean
|
||||
): CreatorChannelCommunityPostRecord?
|
||||
|
||||
fun countCommunityComments(
|
||||
postId: Long,
|
||||
viewerId: Long,
|
||||
creatorId: Long
|
||||
): Int
|
||||
|
||||
fun findCommunityComments(
|
||||
postId: Long,
|
||||
viewerId: Long,
|
||||
creatorId: Long,
|
||||
offset: Long,
|
||||
limit: Int
|
||||
): List<CreatorChannelCommunityCommentRecord>
|
||||
|
||||
fun findLatestRepliesByCommentIds(
|
||||
commentIds: List<Long>,
|
||||
viewerId: Long
|
||||
): List<CreatorChannelCommunityCommentRecord>
|
||||
|
||||
fun findRootCommentContext(
|
||||
commentId: Long,
|
||||
viewerId: Long,
|
||||
canViewAdultContent: Boolean
|
||||
): CreatorChannelCommunityCommentContextRecord?
|
||||
|
||||
fun countCommunityReplies(
|
||||
commentId: Long,
|
||||
viewerId: Long
|
||||
): Int
|
||||
|
||||
fun findCommunityReplies(
|
||||
commentId: Long,
|
||||
viewerId: Long,
|
||||
offset: Long,
|
||||
limit: Int
|
||||
): List<CreatorChannelCommunityCommentRecord>
|
||||
}
|
||||
|
||||
data class CreatorChannelCommunityCreatorRecord(
|
||||
@@ -54,3 +97,21 @@ data class CreatorChannelCommunityPostRecord(
|
||||
val isPinned: Boolean,
|
||||
val isLiked: Boolean
|
||||
)
|
||||
|
||||
data class CreatorChannelCommunityCommentRecord(
|
||||
val commentId: Long,
|
||||
val parentCommentId: Long?,
|
||||
val postId: Long,
|
||||
val writerId: Long,
|
||||
val writerProfilePath: String?,
|
||||
val writerNickname: String,
|
||||
val content: String,
|
||||
val createdAt: LocalDateTime
|
||||
)
|
||||
|
||||
data class CreatorChannelCommunityCommentContextRecord(
|
||||
val commentId: Long,
|
||||
val postId: Long,
|
||||
val creatorId: Long,
|
||||
val isCommentAvailable: Boolean
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user