perfect comments relates display and optimize some code

This commit is contained in:
xing 2024-01-10 23:50:23 +08:00
parent 8d3197ee98
commit 6044b8eaec
18 changed files with 207 additions and 96 deletions

View File

@ -48,8 +48,10 @@
- 博客页面至多显示数量 - 博客页面至多显示数量
- Feed中显示最近数量 - Feed中显示最近数量
- 讨论 - 讨论
- 其他评论设置-启用评论嵌套,最多嵌套层数 - 其他评论设置
- 在每个页面顶部显示 `新旧`评论 - `启用|禁止`评论嵌套,最多嵌套层数
- 分页显示评论,每页显示评论条数,默认显示`最前/后`页
- 在每个页面顶部显示 `新旧`评论
#### 主题支持程度 #### 主题支持程度

View File

@ -47,7 +47,7 @@ func InitActionsCommonCache() {
return config.GetConfig().CacheTime.RecentPostCacheTime return config.GetConfig().CacheTime.RecentPostCacheTime
}) })
cachemanager.NewVarMemoryCache(dao.RecentComments, c.CacheTime.RecentCommentsCacheTime, "recentComments", func() time.Duration { cachemanager.NewVarMemoryCache(RecentComment, c.CacheTime.RecentCommentsCacheTime, "recentComments", func() time.Duration {
return config.GetConfig().CacheTime.RecentCommentsCacheTime return config.GetConfig().CacheTime.RecentCommentsCacheTime
}) })
@ -58,6 +58,9 @@ func InitActionsCommonCache() {
cachemanager.NewMemoryMapCache(nil, PostTopComments, 30*time.Second, "PostCommentsIds", func() time.Duration { cachemanager.NewMemoryMapCache(nil, PostTopComments, 30*time.Second, "PostCommentsIds", func() time.Duration {
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
}) })
cachemanager.NewMemoryMapCache(nil, dao.PostTopCommentNum, 30*time.Second, "postTopCommentsNum", func() time.Duration {
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
})
cachemanager.NewMemoryMapCache(dao.GetCommentByIds, nil, time.Hour, "postCommentData", func() time.Duration { cachemanager.NewMemoryMapCache(dao.GetCommentByIds, nil, time.Hour, "postCommentData", func() time.Duration {
return config.GetConfig().CacheTime.CommentsCacheTime return config.GetConfig().CacheTime.CommentsCacheTime
@ -131,7 +134,7 @@ func CategoriesTags(ctx context.Context, t ...string) []models.TermsMy {
if len(t) > 0 { if len(t) > 0 {
tt = t[0] tt = t[0]
} }
r, err := cachemanager.Get[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second) r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
logs.IfError(err, "get category fail") logs.IfError(err, "get category fail")
return r return r
} }
@ -140,7 +143,7 @@ func AllCategoryTagsNames(ctx context.Context, t ...string) map[string]struct{}
if len(t) > 0 { if len(t) > 0 {
tt = t[0] tt = t[0]
} }
r, err := cachemanager.Get[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second) r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
if err != nil { if err != nil {
logs.Error(err, "get category fail") logs.Error(err, "get category fail")
return nil return nil

View File

@ -2,13 +2,15 @@ package cache
import ( import (
"context" "context"
"fmt"
"github.com/fthvgb1/wp-go/app/pkg/dao" "github.com/fthvgb1/wp-go/app/pkg/dao"
"github.com/fthvgb1/wp-go/app/pkg/logs" "github.com/fthvgb1/wp-go/app/pkg/logs"
"github.com/fthvgb1/wp-go/app/pkg/models" "github.com/fthvgb1/wp-go/app/pkg/models"
"github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache" "github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/cache/cachemanager" "github.com/fthvgb1/wp-go/cache/cachemanager"
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/number" "github.com/fthvgb1/wp-go/helper/number"
str "github.com/fthvgb1/wp-go/helper/strings"
"time" "time"
) )
@ -23,7 +25,7 @@ func RecentComments(ctx context.Context, n int) (r []models.Comments) {
} }
func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) { func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) {
ids, err := cachemanager.Get[[]uint64]("PostCommentsIds", ctx, Id, time.Second) ids, err := cachemanager.GetBy[[]uint64]("PostCommentsIds", ctx, Id, time.Second)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -31,11 +33,11 @@ func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) {
} }
func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) { func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) {
return cachemanager.Get[models.Comments]("postCommentData", ctx, id, time.Second) return cachemanager.GetBy[models.Comments]("postCommentData", ctx, id, time.Second)
} }
func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) { func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) {
return cachemanager.GetMultiple[models.Comments]("postCommentData", ctx, ids, time.Second) return cachemanager.GetBatchBy[models.Comments]("postCommentData", ctx, ids, time.Second)
} }
func NewCommentCache() *cache.MapCache[string, string] { func NewCommentCache() *cache.MapCache[string, string] {
@ -43,17 +45,67 @@ func NewCommentCache() *cache.MapCache[string, string] {
return r return r
} }
func PostTopComments(ctx context.Context, _ string, a ...any) (helper.PaginationData[uint64], error) { func PostTopComments(ctx context.Context, _ string, a ...any) ([]uint64, error) {
postId := a[0].(uint64) postId := a[0].(uint64)
page := a[1].(int) page := a[1].(int)
limit := a[2].(int) limit := a[2].(int)
total := a[3].(int) total := a[3].(int)
v, total, err := dao.PostCommentsIds(ctx, postId, page, limit, total) v, _, err := dao.PostCommentsIds(ctx, postId, page, limit, total)
if err != nil { if err != nil {
return helper.PaginationData[uint64]{}, err return nil, err
} }
return helper.PaginationData[uint64]{ return v, nil
Data: v, }
TotalRaw: total,
}, nil func RecentComment(ctx context.Context, a ...any) (r []models.Comments, err error) {
r, err = dao.RecentComments(ctx, a...)
if err != nil {
return r, err
}
for i, comment := range r {
r[i].CommentAuthorUrl, err = GetCommentUrl(ctx, comment.CommentId, comment.CommentPostId)
if err != nil {
return nil, err
}
}
return
}
func GetCommentUrl(ctx context.Context, commentId, postId uint64) (string, error) {
if wpconfig.GetOption("page_comments") != "1" {
return fmt.Sprintf("/p/%d#comment-%d", postId, commentId), nil
}
commentsPerPage := str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
topCommentId, err := AncestorCommentId(ctx, commentId)
if err != nil {
return "", err
}
totalNum, err := cachemanager.GetBy[int]("postTopCommentsNum", ctx, postId, time.Second)
if err != nil {
return "", err
}
if totalNum <= commentsPerPage {
return fmt.Sprintf("/p/%d#comment-%d", postId, commentId), nil
}
num, err := dao.PreviousCommentNum(ctx, topCommentId, postId)
if err != nil {
return "", err
}
order := wpconfig.GetOption("comment_order")
page := number.DivideCeil(num+1, commentsPerPage)
if order == "desc" {
page = number.DivideCeil(totalNum-num, commentsPerPage)
}
return fmt.Sprintf("/p/%d/comment-page-%d/#comment-%d", postId, page, commentId), nil
}
func AncestorCommentId(ctx context.Context, commentId uint64) (uint64, error) {
comment, err := cachemanager.GetBy[models.Comments]("postCommentData", ctx, commentId, time.Second)
if err != nil {
return 0, err
}
if comment.CommentParent == 0 {
return comment.CommentId, nil
}
return AncestorCommentId(ctx, comment.CommentParent)
} }

View File

@ -111,7 +111,7 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) {
if err != nil { if err != nil {
return return
} }
comments, err := cachemanager.GetMultiple[models.Comments]("postCommentData", c, ids, time.Second) comments, err := cachemanager.GetBatchBy[models.Comments]("postCommentData", c, ids, time.Second)
if err != nil { if err != nil {
return return
} }
@ -182,7 +182,7 @@ func commentsFeed(c context.Context, _ ...any) (r []string, err error) {
} }
return rss2.Item{ return rss2.Item{
Title: fmt.Sprintf("%s对《%s》的评论", t.CommentAuthor, post.PostTitle), Title: fmt.Sprintf("%s对《%s》的评论", t.CommentAuthor, post.PostTitle),
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId), Link: t.CommentAuthorUrl,
Creator: t.CommentAuthor, Creator: t.CommentAuthor,
Description: desc, Description: desc,
PubDate: t.CommentDateGmt.Format(timeFormat), PubDate: t.CommentDateGmt.Format(timeFormat),

View File

@ -7,8 +7,8 @@ import (
) )
func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) { func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) {
return cachemanager.GetMultiple[map[string]any]("postMetaData", ctx, ids, time.Second) return cachemanager.GetBatchBy[map[string]any]("postMetaData", ctx, ids, time.Second)
} }
func GetPostMetaByPostId(ctx context.Context, id uint64) (map[string]any, error) { func GetPostMetaByPostId(ctx context.Context, id uint64) (map[string]any, error) {
return cachemanager.Get[map[string]any]("postMetaData", ctx, id, time.Second) return cachemanager.GetBy[map[string]any]("postMetaData", ctx, id, time.Second)
} }

View File

@ -15,15 +15,15 @@ import (
) )
func GetPostById(ctx context.Context, id uint64) (models.Posts, error) { func GetPostById(ctx context.Context, id uint64) (models.Posts, error) {
return cachemanager.Get[models.Posts]("postData", ctx, id, time.Second) return cachemanager.GetBy[models.Posts]("postData", ctx, id, time.Second)
} }
func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) { func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) {
return cachemanager.GetMultiple[models.Posts]("postData", ctx, ids, time.Second) return cachemanager.GetBatchBy[models.Posts]("postData", ctx, ids, time.Second)
} }
func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) { func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
ids, err := cachemanager.Get[dao.PostIds]("searchPostIds", ctx, key, time.Second, args...) ids, err := cachemanager.GetBy[dao.PostIds]("searchPostIds", ctx, key, time.Second, args...)
if err != nil { if err != nil {
return return
} }
@ -33,7 +33,7 @@ func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts,
} }
func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) { func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
ids, err := cachemanager.Get[dao.PostIds]("listPostIds", ctx, key, time.Second, args...) ids, err := cachemanager.GetBy[dao.PostIds]("listPostIds", ctx, key, time.Second, args...)
if err != nil { if err != nil {
return return
} }
@ -59,7 +59,7 @@ func RecentPosts(ctx context.Context, n int) (r []models.Posts) {
} }
func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next models.Posts, err error) { func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next models.Posts, err error) {
postCtx, err := cachemanager.Get[dao.PostContext]("postContext", ctx, id, time.Second, date) postCtx, err := cachemanager.GetBy[dao.PostContext]("postContext", ctx, id, time.Second, date)
if err != nil { if err != nil {
return models.Posts{}, models.Posts{}, err return models.Posts{}, models.Posts{}, err
} }
@ -69,7 +69,7 @@ func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next
} }
func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, order string) (r []models.Posts, total int, err error) { func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, order string) (r []models.Posts, total int, err error) {
res, err := cachemanager.Get[[]uint64]("monthPostIds", ctx, fmt.Sprintf("%s%s", year, month), time.Second, year, month) res, err := cachemanager.GetBy[[]uint64]("monthPostIds", ctx, fmt.Sprintf("%s%s", year, month), time.Second, year, month)
if err != nil { if err != nil {
return return
} }

View File

@ -9,7 +9,7 @@ import (
) )
func GetUserByName(ctx context.Context, username string) (models.Users, error) { func GetUserByName(ctx context.Context, username string) (models.Users, error) {
return cachemanager.Get[models.Users]("usernameMapToUserData", ctx, username, time.Second) return cachemanager.GetBy[models.Users]("usernameMapToUserData", ctx, username, time.Second)
} }
func GetAllUsername(ctx context.Context) (map[string]struct{}, error) { func GetAllUsername(ctx context.Context) (map[string]struct{}, error) {
@ -17,7 +17,7 @@ func GetAllUsername(ctx context.Context) (map[string]struct{}, error) {
} }
func GetUserById(ctx context.Context, uid uint64) models.Users { func GetUserById(ctx context.Context, uid uint64) models.Users {
r, err := cachemanager.Get[models.Users]("userData", ctx, uid, time.Second) r, err := cachemanager.GetBy[models.Users]("userData", ctx, uid, time.Second)
logs.IfError(err, "get user", uid) logs.IfError(err, "get user", uid)
return r return r
} }

View File

@ -91,25 +91,51 @@ func CommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
return str.ToInteger(n, 0), err return str.ToInteger(n, 0), err
} }
func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, _ ...any) ([]uint64, int, error) { func PostTopCommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
order := wpconfig.GetOption("comment_order") v, err := model.GetField[models.Comments](ctx, "count(*) num", model.Conditions(
model.Where(postTopCommentNumWhere(postId)),
))
if err != nil {
return 0, err
}
return str.ToInteger(v, 0), nil
}
func postTopCommentNumWhere(postId uint64) model.SqlBuilder {
threadComments := wpconfig.GetOption("thread_comments") threadComments := wpconfig.GetOption("thread_comments")
pageComments := wpconfig.GetOption("page_comments")
where := model.SqlBuilder{ where := model.SqlBuilder{
{"comment_approved", "1"}, {"comment_approved", "1"},
{"comment_post_ID", "=", number.IntToString(postId), "int"}, {"comment_post_ID", "=", number.IntToString(postId), "int"},
} }
if threadComments == "1" || "1" == wpconfig.GetOption("thread_comments_depth") { if pageComments != "1" || threadComments == "1" || "1" == wpconfig.GetOption("thread_comments_depth") {
where = append(where, []string{"comment_parent", "0"}) where = append(where, []string{"comment_parent", "0"})
} }
r, total, err := model.Pagination[models.Comments](ctx, model.Conditions( return where
model.Where(where), }
func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, _ ...any) ([]uint64, int, error) {
order := wpconfig.GetOption("comment_order")
pageComments := wpconfig.GetOption("page_comments")
condition := model.Conditions(
model.Where(postTopCommentNumWhere(postId)),
model.TotalRaw(totalRaw), model.TotalRaw(totalRaw),
model.Fields("comment_ID"), model.Fields("comment_ID"),
model.Order(model.SqlBuilder{ model.Order(model.SqlBuilder{
{"comment_date_gmt", order}, {"comment_date_gmt", order},
{"comment_ID", "asc"}, {"comment_ID", "asc"},
}), }),
), page, limit) )
var r []models.Comments
var total int
var err error
if pageComments != "1" {
r, err = model.ChunkFind[models.Comments](ctx, 300, condition)
total = len(r)
} else {
r, total, err = model.Pagination[models.Comments](ctx, condition, page, limit)
}
if err != nil && errors.Is(err, sql.ErrNoRows) { if err != nil && errors.Is(err, sql.ErrNoRows) {
err = nil err = nil
} }
@ -133,8 +159,27 @@ func CommentChildren(ctx context.Context, commentIds []uint64, _ ...any) (r map[
} }
return return
} }
r = slice.GroupBy(rr, func(v models.Comments) (uint64, uint64) { rrr := slice.GroupBy(rr, func(v models.Comments) (uint64, uint64) {
return v.CommentParent, v.CommentId return v.CommentParent, v.CommentId
}) })
r = make(map[uint64][]uint64)
for _, id := range commentIds {
r[id] = rrr[id]
}
return return
} }
func PreviousCommentNum(ctx context.Context, commentId, postId uint64) (int, error) {
v, err := model.GetField[models.Comments](ctx, "count(*)", model.Conditions(
model.Where(model.SqlBuilder{
{"comment_approved", "1"},
{"comment_post_ID", "=", number.IntToString(postId), "int"},
{"comment_ID", "<", number.IntToString(commentId), "int"},
{"comment_parent", "=", "0", "int"},
}),
))
if err != nil {
return 0, err
}
return str.ToInteger(v, 0), nil
}

View File

@ -29,7 +29,7 @@ type Comments struct {
type CommentHtml interface { type CommentHtml interface {
FormatLi(c context.Context, m models.Comments, depth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string FormatLi(c context.Context, m models.Comments, depth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string
FloorOrder(wpOrder string, i, j models.Comments) bool FloorOrder(i, j models.Comments) bool
} }
func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string { func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string {
@ -146,7 +146,7 @@ func (c CommonCommentFormat) FormatLi(_ context.Context, m models.Comments, curr
return FormatLi(li, m, respondsFn, currentDepth, maxDepth, page, isTls, isThreadComments, eo, parent) return FormatLi(li, m, respondsFn, currentDepth, maxDepth, page, isTls, isThreadComments, eo, parent)
} }
func (c CommonCommentFormat) FloorOrder(wpOrder string, i, j models.Comments) bool { func (c CommonCommentFormat) FloorOrder(i, j models.Comments) bool {
return i.CommentId > j.CommentId return i.CommentId > j.CommentId
} }

View File

@ -71,7 +71,7 @@ func PostsMore(id uint64, content, closeTag string) string {
} }
func Digest(ctx context.Context, post *models.Posts, limit int) { func Digest(ctx context.Context, post *models.Posts, limit int) {
content, _ := cachemanager.Get[string]("digestPlugin", ctx, post.Id, time.Second, ctx, post.PostContent, post.Id, limit) content, _ := cachemanager.GetBy[string]("digestPlugin", ctx, post.Id, time.Second, ctx, post.PostContent, post.Id, limit)
post.PostContent = content post.PostContent = content
} }

View File

@ -41,11 +41,14 @@ type CommentHandle struct {
threadComments bool threadComments bool
} }
func (c CommentHandle) findComments(ctx context.Context, timeout time.Duration, comments []models.Comments) ([]models.Comments, error) { func (c CommentHandle) findGrandchildComments(ctx context.Context, timeout time.Duration, comments []models.Comments) ([]models.Comments, error) {
parentIds := slice.Map(comments, func(t models.Comments) uint64 { parentIds := slice.Map(comments, func(t models.Comments) uint64 {
return t.CommentId return t.CommentId
}) })
children, err := c.children.GetCacheBatch(ctx, parentIds, timeout) children, err := c.children.GetCacheBatch(ctx, parentIds, timeout)
if err != nil {
return nil, err
}
rr := slice.FilterAndMap(children, func(t []uint64) ([]uint64, bool) { rr := slice.FilterAndMap(children, func(t []uint64) ([]uint64, bool) {
return t, len(t) > 0 return t, len(t) > 0
}) })
@ -57,13 +60,13 @@ func (c CommentHandle) findComments(ctx context.Context, timeout time.Duration,
if err != nil { if err != nil {
return nil, err return nil, err
} }
rrr, err := c.findComments(ctx, timeout, r) rrr, err := c.findGrandchildComments(ctx, timeout, r)
if err != nil { if err != nil {
return nil, err return nil, err
} }
comments = append(comments, rrr...) comments = append(comments, rrr...)
slice.Sort(comments, func(i, j models.Comments) bool { slice.Sort(comments, func(i, j models.Comments) bool {
return c.html.FloorOrder(c.order, i, j) return c.html.FloorOrder(i, j)
}) })
return comments, nil return comments, nil
} }
@ -75,12 +78,12 @@ func (c CommentHandle) formatComments(ctx context.Context, ids []uint64, timeout
} }
if c.depth > 1 && c.depth < c.maxDepth { if c.depth > 1 && c.depth < c.maxDepth {
slice.Sort(comments, func(i, j models.Comments) bool { slice.Sort(comments, func(i, j models.Comments) bool {
return c.html.FloorOrder(c.order, i, j) return c.html.FloorOrder(i, j)
}) })
} }
fixChildren := false fixChildren := false
if c.depth >= c.maxDepth { if c.depth >= c.maxDepth {
comments, err = c.findComments(ctx, timeout, comments) comments, err = c.findGrandchildComments(ctx, timeout, comments)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -97,10 +100,9 @@ func (c CommentHandle) formatComments(ctx context.Context, ids []uint64, timeout
var children []uint64 var children []uint64
if !fixChildren { if !fixChildren {
children, err = c.children.GetCache(ctx, comment.CommentId, timeout) children, err = c.children.GetCache(ctx, comment.CommentId, timeout)
} if err != nil {
return "", err
if err != nil { }
return "", err
} }
if c.threadComments && len(children) > 0 && c.depth < c.maxDepth+1 { if c.threadComments && len(children) > 0 && c.depth < c.maxDepth+1 {
parent = "parent" parent = "parent"

View File

@ -59,9 +59,9 @@ func RecentComments(h *wp.Handle, id string) string {
comments := slice.Map(cache.RecentComments(h.C, int(conf["number"].(int64))), func(t models.Comments) string { comments := slice.Map(cache.RecentComments(h.C, int(conf["number"].(int64))), func(t models.Comments) string {
return fmt.Sprintf(` <li> return fmt.Sprintf(` <li>
<span class="comment-author-link">%s</span>发表在 <span class="comment-author-link">%s</span>发表在
<a href="/p/%v#comment-%v">%s</a> <a href="%s">%s</a>
</li>`, t.CommentAuthor, t.CommentPostId, t.CommentId, t.PostTitle) </li>`, t.CommentAuthor, t.CommentAuthorUrl, t.PostTitle)
}) })
s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n")) s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
return h.DoActionFilter(widgets.RecentComments, str.Replace(s, args)) return h.DoActionFilter(widgets.RecentComments, str.Replace(s, args))

View File

@ -11,11 +11,11 @@ import (
"github.com/fthvgb1/wp-go/app/plugins/wpposts" "github.com/fthvgb1/wp-go/app/plugins/wpposts"
"github.com/fthvgb1/wp-go/app/wpconfig" "github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache/cachemanager" "github.com/fthvgb1/wp-go/cache/cachemanager"
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/number" "github.com/fthvgb1/wp-go/helper/number"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/plugin/pagination" "github.com/fthvgb1/wp-go/plugin/pagination"
"net/http" "net/http"
"strings"
"time" "time"
) )
@ -92,27 +92,52 @@ func (d *DetailHandle) Comment() {
d.ginH["totalCommentNum"] = 0 d.ginH["totalCommentNum"] = 0
d.ginH["totalCommentPage"] = 1 d.ginH["totalCommentPage"] = 1
d.ginH["commentPageNav"] = "" d.ginH["commentPageNav"] = ""
d.ginH["commentOrder"] = wpconfig.GetOption("comment_order") order := wpconfig.GetOption("comment_order")
d.ginH["commentOrder"] = order
d.Limit = str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
pageComments := wpconfig.GetOption("page_comments")
num, err := cachemanager.GetBy[int]("commentNumber", d.C, d.Post.Id, time.Second)
if err != nil {
d.SetErr(err)
return
}
if num < 1 {
return
}
topNum, err := cachemanager.GetBy[int]("postTopCommentsNum", d.C, d.Post.Id, time.Second)
if err != nil {
d.SetErr(err)
return
}
totalPage := number.DivideCeil(topNum, d.Limit)
if !strings.Contains(d.C.Request.URL.Path, "comment-page") {
defaultCommentsPage := wpconfig.GetOption("default_comments_page")
if order == "desc" && defaultCommentsPage == "oldest" || order == "asc" && defaultCommentsPage == "newest" {
d.C.AddParam("page", number.IntToString(totalPage))
}
}
d.Page = str.ToInteger(d.C.Param("page"), 1) d.Page = str.ToInteger(d.C.Param("page"), 1)
d.ginH["currentPage"] = d.Page d.ginH["currentPage"] = d.Page
d.Limit = str.ToInteger(wpconfig.GetOption("comments_per_page"), 5) var key string
key := fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit) if pageComments != "1" {
data, err := cachemanager.Get[helper.PaginationData[uint64]]("PostCommentsIds", d.C, key, time.Second, d.Post.Id, d.Page, d.Limit, 0) key = number.IntToString(d.Post.Id)
if err != nil { } else {
d.SetErr(err) key = fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit)
return }
} d.ginH["page_comments"] = pageComments
ids := data.Data d.ginH["totalCommentPage"] = totalPage
totalCommentNum := data.TotalRaw if totalPage < d.Page {
d.TotalRaw = totalCommentNum d.SetErr(errors.New("curren page above total page"))
num, err := cachemanager.Get[int]("commentNumber", d.C, d.Post.Id, time.Second) return
}
data, err := cachemanager.GetBy[[]uint64]("PostCommentsIds", d.C, key, time.Second, d.Post.Id, d.Page, d.Limit, topNum)
if err != nil { if err != nil {
d.SetErr(err) d.SetErr(err)
return return
} }
d.TotalRaw = topNum
d.ginH["totalCommentNum"] = num d.ginH["totalCommentNum"] = num
d.ginH["totalCommentPage"] = number.DivideCeil(totalCommentNum, d.Limit) d.Comments = data
d.Comments = ids
} }
func (d *DetailHandle) RenderComment() { func (d *DetailHandle) RenderComment() {
@ -138,8 +163,9 @@ func (d *DetailHandle) RenderComment() {
if d.CommentPageEle == nil { if d.CommentPageEle == nil {
d.CommentPageEle = plugins.TwentyFifteenCommentPagination() d.CommentPageEle = plugins.TwentyFifteenCommentPagination()
} }
d.ginH["commentPageNav"] = pagination.Paginate(d.CommentPageEle, d.TotalRaw, d.Limit, d.Page, 1, *d.C.Request.URL, d.IsHttps()) if wpconfig.GetOption("page_comments") == "1" {
d.ginH["commentPageNav"] = pagination.Paginate(d.CommentPageEle, d.TotalRaw, d.Limit, d.Page, 1, *d.C.Request.URL, d.IsHttps())
}
} }
func (d *DetailHandle) ContextPost() { func (d *DetailHandle) ContextPost() {

View File

@ -100,7 +100,7 @@ func PushMangerMap[K comparable, V any](name string, m *cache.MapCache[K, V]) {
}) })
} }
func Get[T any, K comparable](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) { func GetBy[T any, K comparable](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
ct = context.WithValue(ct, "getCache", name) ct = context.WithValue(ct, "getCache", name)
ca, err := getMap[K, T](name) ca, err := getMap[K, T](name)
if err != nil { if err != nil {
@ -125,7 +125,7 @@ func getMap[K comparable, T any](name string) (*cache.MapCache[K, T], error) {
} }
return vk, nil return vk, nil
} }
func GetMultiple[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) { func GetBatchBy[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
ct = context.WithValue(ct, "getCache", name) ct = context.WithValue(ct, "getCache", name)
ca, err := getMap[K, T](name) ca, err := getMap[K, T](name)
if err != nil { if err != nil {
@ -138,7 +138,7 @@ func GetMultiple[T any, K comparable](name string, ct context.Context, key []K,
r = vv r = vv
return return
} }
func GetMultipleToMap[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r map[K]T, err error) { func GetBatchByToMap[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r map[K]T, err error) {
ct = context.WithValue(ct, "getCache", name) ct = context.WithValue(ct, "getCache", name)
ca, err := getMap[K, T](name) ca, err := getMap[K, T](name)
if err != nil { if err != nil {

View File

@ -28,7 +28,7 @@ func TestFlushMapVal(t *testing.T) {
return r, nil return r, nil
}, nil, time.Second, "test") }, nil, time.Second, "test")
gets, err := GetMultiple[int]("test", ctx, number.Range(1, 10), time.Second) gets, err := GetBatchBy[int]("test", ctx, number.Range(1, 10), time.Second)
if err != nil { if err != nil {
t.Fatal(t, "err:", err) t.Fatal(t, "err:", err)
} }
@ -48,7 +48,7 @@ func TestFlushMapVal(t *testing.T) {
FlushMapVal("test", 3, 4) FlushMapVal("test", 3, 4)
fmt.Println(vv.Get(ctx, 3)) fmt.Println(vv.Get(ctx, 3))
fmt.Println(vv.Get(ctx, 4)) fmt.Println(vv.Get(ctx, 4))
get, err := Get[int]("test", ctx, 3, time.Second) get, err := GetBy[int]("test", ctx, 3, time.Second)
if err != nil { if err != nil {
t.Fatal(t, "err", err) t.Fatal(t, "err", err)
} }
@ -85,7 +85,7 @@ func TestSetExpireTime(t *testing.T) {
cc.Set(ctx, "ww", "vv") cc.Set(ctx, "ww", "vv")
m, err := cc.GetBatchToMap(ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second) m, err := cc.GetBatchToMap(ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second)
fmt.Println(m, err) fmt.Println(m, err)
fmt.Println(GetMultipleToMap[string]("xx", ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second)) fmt.Println(GetBatchByToMap[string]("xx", ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second))
v := NewVarMemoryCache(func(ct context.Context, a ...any) (string, error) { v := NewVarMemoryCache(func(ct context.Context, a ...any) (string, error) {
return "ssss", nil return "ssss", nil
}, 3*time.Second, "ff") }, 3*time.Second, "ff")
@ -100,7 +100,7 @@ func TestSetMapCache(t *testing.T) {
fmt.Println("memory cache") fmt.Println("memory cache")
return strings.Repeat(k, 2), nil return strings.Repeat(k, 2), nil
}, time.Hour, "test") }, time.Hour, "test")
fmt.Println(Get[string]("test", ctx, "test", time.Second)) fmt.Println(GetBy[string]("test", ctx, "test", time.Second))
NewMapCache[string, string](xx[string, string]{m: map[string]string{}}, nil, func(ctx2 context.Context, k string, a ...any) (string, error) { NewMapCache[string, string](xx[string, string]{m: map[string]string{}}, nil, func(ctx2 context.Context, k string, a ...any) (string, error) {
fmt.Println("other cache drives. eg: redis,file.....") fmt.Println("other cache drives. eg: redis,file.....")
@ -110,7 +110,7 @@ func TestSetMapCache(t *testing.T) {
if err := SetMapCache("kkk", x); err != nil { if err := SetMapCache("kkk", x); err != nil {
t.Errorf("SetMapCache() error = %v, wantErr %v", err, nil) t.Errorf("SetMapCache() error = %v, wantErr %v", err, nil)
} }
fmt.Println(Get[string]("test", ctx, "test", time.Second)) fmt.Println(GetBy[string]("test", ctx, "test", time.Second))
}) })
} }

View File

@ -1,26 +1,6 @@
package helper package helper
import "context"
type Pagination[T any] interface {
SetData(ctx context.Context, data []T)
GetData(ctx context.Context) []T
TotalRaws(ctx context.Context) int
}
type PaginationData[T any] struct { type PaginationData[T any] struct {
Data []T Data []T
TotalRaw int TotalRaw int
} }
func (p *PaginationData[T]) SetData(ctx context.Context, data []T) {
p.Data = data
}
func (p *PaginationData[T]) GetData(ctx context.Context) []T {
return p.Data
}
func (p *PaginationData[T]) TotalRaws(ctx context.Context) int {
return p.TotalRaw
}

View File

@ -79,7 +79,7 @@ func Limit(limit int) Condition {
} }
} }
// TotalRaw only effect on Pagination,when TotalRaw>0 ,will not query count // TotalRaw only effect on Pagination, ChunkFind,when TotalRaw>0 ,will not query count
func TotalRaw(total int) Condition { func TotalRaw(total int) Condition {
return func(c *QueryCondition) { return func(c *QueryCondition) {
c.TotalRow = total c.TotalRow = total

View File

@ -48,7 +48,8 @@ A WordPress front-end written in Go, with relatively simple functions, only the
- Syndication feeds show the most recent - Syndication feeds show the most recent
- discussion - discussion
- Other comment settings - Other comment settings
- Enable threaded (nested) comments levels deep - `enable|disable` threaded (nested) comments levels deep
- Break comments into pages with top level comments per page number and the `last|first` page displayed by default
- Comments should be displayed with the `newer|older`comments - Comments should be displayed with the `newer|older`comments
#### Theme support #### Theme support