fix bug, optimize code, add some cache comments, add middleware,change pagination nav to mix url plain

This commit is contained in:
xing 2024-01-13 21:15:54 +08:00
parent 6044b8eaec
commit 0352dd0fd0
18 changed files with 353 additions and 152 deletions

View File

@ -7,7 +7,6 @@ import (
"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/cache/cachemanager" "github.com/fthvgb1/wp-go/cache/cachemanager"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/safety" "github.com/fthvgb1/wp-go/safety"
"time" "time"
) )
@ -78,7 +77,7 @@ func InitActionsCommonCache() {
return config.GetConfig().CacheTime.UserInfoCacheTime return config.GetConfig().CacheTime.UserInfoCacheTime
}) })
cachemanager.NewMemoryMapCache(nil, dao.GetUserByName, c.CacheTime.UserInfoCacheTime, "usernameMapToUserData", func() time.Duration { cachemanager.NewMemoryMapCache(nil, dao.GetUserByName, c.CacheTime.UserInfoCacheTime, "usernameToUserData", func() time.Duration {
return config.GetConfig().CacheTime.UserInfoCacheTime return config.GetConfig().CacheTime.UserInfoCacheTime
}) })
@ -88,7 +87,7 @@ func InitActionsCommonCache() {
cachemanager.NewVarMemoryCache(feed, time.Hour, "feed") cachemanager.NewVarMemoryCache(feed, time.Hour, "feed")
cachemanager.NewMemoryMapCache(nil, postFeed, time.Hour, "postFeed") cachemanager.NewMemoryMapCache(nil, PostFeed, time.Hour, "postFeed")
cachemanager.NewVarMemoryCache(commentsFeed, time.Hour, "commentsFeed") cachemanager.NewVarMemoryCache(commentsFeed, time.Hour, "commentsFeed")
@ -125,30 +124,3 @@ func Archives(ctx context.Context) []models.PostArchive {
} }
return data return data
} }
// CategoriesTags categories or tags
//
// t is constraints.Tag or constraints.Category
func CategoriesTags(ctx context.Context, t ...string) []models.TermsMy {
tt := ""
if len(t) > 0 {
tt = t[0]
}
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
logs.IfError(err, "get category fail")
return r
}
func AllCategoryTagsNames(ctx context.Context, t ...string) map[string]struct{} {
tt := ""
if len(t) > 0 {
tt = t[0]
}
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
if err != nil {
logs.Error(err, "get category fail")
return nil
}
return slice.ToMap(r, func(t models.TermsMy) (string, struct{}) {
return t.Name, struct{}{}
}, true)
}

39
app/pkg/cache/categoryandtag.go vendored Normal file
View File

@ -0,0 +1,39 @@
package cache
import (
"context"
"github.com/fthvgb1/wp-go/app/pkg/logs"
"github.com/fthvgb1/wp-go/app/pkg/models"
"github.com/fthvgb1/wp-go/cache/cachemanager"
"github.com/fthvgb1/wp-go/helper/slice"
"time"
)
// CategoriesTags get all categories or tags
//
// query func see dao.CategoriesAndTags
//
// t is constraints.Tag or constraints.Category
func CategoriesTags(ctx context.Context, t ...string) []models.TermsMy {
tt := ""
if len(t) > 0 {
tt = t[0]
}
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
logs.IfError(err, "get category fail")
return r
}
func AllCategoryTagsNames(ctx context.Context, t ...string) map[string]struct{} {
tt := ""
if len(t) > 0 {
tt = t[0]
}
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
if err != nil {
logs.Error(err, "get category fail")
return nil
}
return slice.ToMap(r, func(t models.TermsMy) (string, struct{}) {
return t.Name, struct{}{}
}, true)
}

View File

@ -9,11 +9,13 @@ import (
"github.com/fthvgb1/wp-go/app/wpconfig" "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" str "github.com/fthvgb1/wp-go/helper/strings"
"time" "time"
) )
// RecentComments query func see RecentComment
func RecentComments(ctx context.Context, n int) (r []models.Comments) { func RecentComments(ctx context.Context, n int) (r []models.Comments) {
nn := number.Max(n, 10) nn := number.Max(n, 10)
r, err := cachemanager.GetVarVal[[]models.Comments]("recentComments", ctx, time.Second, ctx, nn) r, err := cachemanager.GetVarVal[[]models.Comments]("recentComments", ctx, time.Second, ctx, nn)
@ -24,18 +26,25 @@ func RecentComments(ctx context.Context, n int) (r []models.Comments) {
return return
} }
func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) { // PostTopLevelCommentIds query func see PostTopComments
ids, err := cachemanager.GetBy[[]uint64]("PostCommentsIds", ctx, Id, time.Second) func PostTopLevelCommentIds(ctx context.Context, postId uint64, page, limit, total int, order string, a ...any) ([]uint64, error) {
if err != nil { var key string
return nil, err if len(a) > 0 {
key = helper.ParseArgs("", a...)
} }
return GetCommentDataByIds(ctx, ids) if key == "" {
key = fmt.Sprintf("%d-%d-%d-%d-%s", postId, page, limit, total, order)
}
return cachemanager.GetBy[[]uint64]("PostCommentsIds", ctx,
key, time.Second, postId, page, limit, 0, order)
} }
// GetCommentById query func see dao.GetCommentByIds
func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) { func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) {
return cachemanager.GetBy[models.Comments]("postCommentData", ctx, id, time.Second) return cachemanager.GetBy[models.Comments]("postCommentData", ctx, id, time.Second)
} }
// GetCommentDataByIds query func see dao.GetCommentByIds
func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) { func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) {
return cachemanager.GetBatchBy[models.Comments]("postCommentData", ctx, ids, time.Second) return cachemanager.GetBatchBy[models.Comments]("postCommentData", ctx, ids, time.Second)
} }
@ -50,7 +59,11 @@ func PostTopComments(ctx context.Context, _ string, a ...any) ([]uint64, error)
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, _, err := dao.PostCommentsIds(ctx, postId, page, limit, total) order := helper.ParseArgs("", a...)
if order == "" {
order = wpconfig.GetOption("comment_order")
}
v, _, err := dao.PostCommentsIds(ctx, postId, page, limit, total, order)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -100,7 +113,7 @@ func GetCommentUrl(ctx context.Context, commentId, postId uint64) (string, error
} }
func AncestorCommentId(ctx context.Context, commentId uint64) (uint64, error) { func AncestorCommentId(ctx context.Context, commentId uint64) (uint64, error) {
comment, err := cachemanager.GetBy[models.Comments]("postCommentData", ctx, commentId, time.Second) comment, err := GetCommentById(ctx, commentId)
if err != nil { if err != nil {
return 0, err return 0, err
} }

28
app/pkg/cache/feed.go vendored
View File

@ -2,6 +2,7 @@ package cache
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"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"
@ -44,6 +45,7 @@ func FeedCache() *cache.VarCache[[]string] {
return r return r
} }
// PostFeedCache query func see PostFeed
func PostFeedCache() *cache.MapCache[string, string] { func PostFeedCache() *cache.MapCache[string, string] {
r, _ := cachemanager.GetMapCache[string, string]("postFeed") r, _ := cachemanager.GetMapCache[string, string]("postFeed")
return r return r
@ -95,7 +97,7 @@ func feed(c context.Context, _ ...any) (xml []string, err error) {
return return
} }
func postFeed(c context.Context, id string, _ ...any) (x string, err error) { func PostFeed(c context.Context, id string, _ ...any) (x string, err error) {
ID := str.ToInteger[uint64](id, 0) ID := str.ToInteger[uint64](id, 0)
maxId, err := GetMaxPostId(c) maxId, err := GetMaxPostId(c)
logs.IfError(err, "get max post id") logs.IfError(err, "get max post id")
@ -107,11 +109,11 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) {
return return
} }
limit := str.ToInteger(wpconfig.GetOption("comments_per_page"), 10) limit := str.ToInteger(wpconfig.GetOption("comments_per_page"), 10)
ids, _, err := cachemanager.Pagination[uint64]("PostCommentsIds", c, time.Second, ID, 1, limit, "desc") ids, err := PostTopLevelCommentIds(c, ID, 1, limit, 0, "desc", "latest-comment")
if err != nil { if err != nil {
return return
} }
comments, err := cachemanager.GetBatchBy[models.Comments]("postCommentData", c, ids, time.Second) comments, err := GetCommentDataByIds(c, ids)
if err != nil { if err != nil {
return return
} }
@ -127,10 +129,14 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) {
wpposts.PasswdProjectContent(&post) wpposts.PasswdProjectContent(&post)
if len(comments) > 0 { if len(comments) > 0 {
t := comments[len(comments)-1] t := comments[len(comments)-1]
u, err := GetCommentUrl(c, t.CommentId, t.CommentPostId)
if err != nil {
return "", err
}
rs.Items = []rss2.Item{ rs.Items = []rss2.Item{
{ {
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor), Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId), Link: fmt.Sprintf("%s%s", site, u),
Creator: t.CommentAuthor, Creator: t.CommentAuthor,
PubDate: t.CommentDateGmt.Format(timeFormat), PubDate: t.CommentDateGmt.Format(timeFormat),
Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId), Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId),
@ -141,9 +147,14 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) {
} }
} else { } else {
rs.Items = slice.Map(comments, func(t models.Comments) rss2.Item { rs.Items = slice.Map(comments, func(t models.Comments) rss2.Item {
u, er := GetCommentUrl(c, t.CommentId, t.CommentPostId)
if er != nil {
err = errors.Join(err, er)
return rss2.Item{}
}
return rss2.Item{ return rss2.Item{
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor), Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId), Link: fmt.Sprintf("%s%s", site, u),
Creator: t.CommentAuthor, Creator: t.CommentAuthor,
PubDate: t.CommentDateGmt.Format(timeFormat), PubDate: t.CommentDateGmt.Format(timeFormat),
Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId), Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId),
@ -180,9 +191,14 @@ func commentsFeed(c context.Context, _ ...any) (r []string, err error) {
} else { } else {
content = digest.StripTags(t.CommentContent, "") content = digest.StripTags(t.CommentContent, "")
} }
u, er := GetCommentUrl(c, t.CommentId, t.CommentPostId)
if er != nil {
errors.Join(err, er)
}
u = str.Join(site, u)
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: t.CommentAuthorUrl, Link: u,
Creator: t.CommentAuthor, Creator: t.CommentAuthor,
Description: desc, Description: desc,
PubDate: t.CommentDateGmt.Format(timeFormat), PubDate: t.CommentDateGmt.Format(timeFormat),

View File

@ -6,9 +6,12 @@ import (
"time" "time"
) )
// GetPostMetaByPostIds query func see dao.GetPostMetaByPostIds
func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) { func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) {
return cachemanager.GetBatchBy[map[string]any]("postMetaData", ctx, ids, time.Second) return cachemanager.GetBatchBy[map[string]any]("postMetaData", ctx, ids, time.Second)
} }
// GetPostMetaByPostId query func see dao.GetPostMetaByPostIds
func GetPostMetaByPostId(ctx context.Context, id uint64) (map[string]any, error) { func GetPostMetaByPostId(ctx context.Context, id uint64) (map[string]any, error) {
return cachemanager.GetBy[map[string]any]("postMetaData", ctx, id, time.Second) return cachemanager.GetBy[map[string]any]("postMetaData", ctx, id, time.Second)
} }

View File

@ -14,14 +14,17 @@ import (
"time" "time"
) )
// GetPostById query func see dao.GetPostsByIds
func GetPostById(ctx context.Context, id uint64) (models.Posts, error) { func GetPostById(ctx context.Context, id uint64) (models.Posts, error) {
return cachemanager.GetBy[models.Posts]("postData", ctx, id, time.Second) return cachemanager.GetBy[models.Posts]("postData", ctx, id, time.Second)
} }
// GetPostsByIds query func see dao.GetPostsByIds
func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) { func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) {
return cachemanager.GetBatchBy[models.Posts]("postData", ctx, ids, time.Second) return cachemanager.GetBatchBy[models.Posts]("postData", ctx, ids, time.Second)
} }
// SearchPost query func see dao.SearchPostIds
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.GetBy[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 {
@ -32,6 +35,7 @@ func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts,
return return
} }
// PostLists query func see dao.SearchPostIds
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.GetBy[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 {
@ -42,10 +46,12 @@ func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts,
return return
} }
// GetMaxPostId query func see dao.GetMaxPostId
func GetMaxPostId(ctx context.Context) (uint64, error) { func GetMaxPostId(ctx context.Context) (uint64, error) {
return cachemanager.GetVarVal[uint64]("maxPostId", ctx, time.Second) return cachemanager.GetVarVal[uint64]("maxPostId", ctx, time.Second)
} }
// RecentPosts query func see dao.RecentPosts
func RecentPosts(ctx context.Context, n int) (r []models.Posts) { func RecentPosts(ctx context.Context, n int) (r []models.Posts) {
nn := n nn := n
feedNum := str.ToInteger(wpconfig.GetOption("posts_per_rss"), 10) feedNum := str.ToInteger(wpconfig.GetOption("posts_per_rss"), 10)
@ -58,6 +64,7 @@ func RecentPosts(ctx context.Context, n int) (r []models.Posts) {
return return
} }
// GetContextPost query func see dao.GetPostContext
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.GetBy[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 {
@ -68,6 +75,7 @@ func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next
return return
} }
// GetMonthPostIds query func see dao.MonthPost
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.GetBy[[]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 {

View File

@ -8,14 +8,17 @@ import (
"time" "time"
) )
// GetUserByName query func see dao.GetUserByName
func GetUserByName(ctx context.Context, username string) (models.Users, error) { func GetUserByName(ctx context.Context, username string) (models.Users, error) {
return cachemanager.GetBy[models.Users]("usernameMapToUserData", ctx, username, time.Second) return cachemanager.GetBy[models.Users]("usernameToUserData", ctx, username, time.Second)
} }
func GetAllUsername(ctx context.Context) (map[string]struct{}, error) { // GetAllUsername query func see dao.AllUsername
return cachemanager.GetVarVal[map[string]struct{}]("allUsername", ctx, time.Second) func GetAllUsername(ctx context.Context) (map[string]uint64, error) {
return cachemanager.GetVarVal[map[string]uint64]("allUsername", ctx, time.Second)
} }
// GetUserById query func see dao.GetUserById
func GetUserById(ctx context.Context, uid uint64) models.Users { func GetUserById(ctx context.Context, uid uint64) models.Users {
r, err := cachemanager.GetBy[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)

View File

@ -114,9 +114,7 @@ func postTopCommentNumWhere(postId uint64) model.SqlBuilder {
return where return where
} }
func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, _ ...any) ([]uint64, int, error) { func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, order string) ([]uint64, int, error) {
order := wpconfig.GetOption("comment_order")
pageComments := wpconfig.GetOption("page_comments")
condition := model.Conditions( condition := model.Conditions(
model.Where(postTopCommentNumWhere(postId)), model.Where(postTopCommentNumWhere(postId)),
model.TotalRaw(totalRaw), model.TotalRaw(totalRaw),
@ -129,7 +127,7 @@ func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw i
var r []models.Comments var r []models.Comments
var total int var total int
var err error var err error
if pageComments != "1" { if limit < 1 {
r, err = model.ChunkFind[models.Comments](ctx, 300, condition) r, err = model.ChunkFind[models.Comments](ctx, 300, condition)
total = len(r) total = len(r)
} else { } else {

View File

@ -12,21 +12,21 @@ func GetUserById(ctx context.Context, uid uint64, _ ...any) (r models.Users, err
return return
} }
func AllUsername(ctx context.Context, _ ...any) (map[string]struct{}, error) { func AllUsername(ctx context.Context, _ ...any) (map[string]uint64, error) {
r, err := model.SimpleFind[models.Users](ctx, model.SqlBuilder{ r, err := model.SimpleFind[models.Users](ctx, model.SqlBuilder{
{"user_status", "=", "0", "int"}, {"user_status", "=", "0", "int"},
}, "user_login") }, "display_name,ID")
if err != nil { if err != nil {
return nil, err return nil, err
} }
return slice.ToMap(r, func(t models.Users) (string, struct{}) { return slice.ToMap(r, func(t models.Users) (string, uint64) {
return t.UserLogin, struct{}{} return t.DisplayName, t.Id
}, true), nil }, true), nil
} }
func GetUserByName(ctx context.Context, u string, _ ...any) (r models.Users, err error) { func GetUserByName(ctx context.Context, u string, _ ...any) (r models.Users, err error) {
r, err = model.FirstOne[models.Users](ctx, model.SqlBuilder{{ r, err = model.FirstOne[models.Users](ctx, model.SqlBuilder{{
"user_login", u, "display_name", u,
}}, "*", nil) }}, "*", nil)
return return
} }

View File

@ -7,6 +7,7 @@ import (
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"net/url" "net/url"
"regexp" "regexp"
"strconv"
"strings" "strings"
) )
@ -72,8 +73,20 @@ func (p PageEle) Middle(page int, url string) string {
var reg = regexp.MustCompile(`(/page)/(\d+)`) var reg = regexp.MustCompile(`(/page)/(\d+)`)
var commentReg = regexp.MustCompile(`/comment-page-(\d+)`) var commentReg = regexp.MustCompile(`/comment-page-(\d+)`)
var queryParam = []string{"paged", "cat", "m", "author", "tag"}
func (p PageEle) Urls(u url.URL, page int, isTLS bool) string { func (p PageEle) Urls(u url.URL, page int, isTLS bool) string {
var path, query = u.Path, u.RawQuery var path, query = u.Path, u.RawQuery
if path == "/" {
v := u.Query()
for _, q := range queryParam {
if v.Get(q) != "" {
v.Set("paged", strconv.Itoa(page))
return str.Join(path, "?", v.Encode())
}
}
}
if !strings.Contains(path, "/page/") { if !strings.Contains(path, "/page/") {
path = fmt.Sprintf("%s%s", path, "/page/1") path = fmt.Sprintf("%s%s", path, "/page/1")
} }
@ -87,20 +100,32 @@ func (p PageEle) Urls(u url.URL, page int, isTLS bool) string {
if path == "" { if path == "" {
path = "/" path = "/"
} }
return str.Join(path, query) if query != "" {
return str.Join(path, "?", query)
}
return path
} }
func (p CommentPageEle) Urls(u url.URL, page int, isTLS bool) string { func (p CommentPageEle) Urls(u url.URL, page int, isTLS bool) string {
var path, query = u.Path, u.RawQuery var path, query = u.Path, u.RawQuery
if path == "/" {
v := u.Query()
if v.Get("p") != "" {
v.Set("cpage", strconv.Itoa(page))
return str.Join(path, "?", v.Encode(), "#comments")
}
}
if !strings.Contains(path, "/comment-page-") { if !strings.Contains(path, "/comment-page-") {
path = fmt.Sprintf("%s%s", path, "/comment-page-1#comments") path = fmt.Sprintf("%s%s", path, "/comment-page-1")
} }
path = commentReg.ReplaceAllString(path, fmt.Sprintf("/comment-page-%d", page)) path = commentReg.ReplaceAllString(path, fmt.Sprintf("/comment-page-%d", page))
path = strings.Replace(path, "//", "/", -1) path = strings.Replace(path, "//", "/", -1)
ur := str.Join(path, query) ur := path
if !strings.Contains(ur, "#comments") { if query != "" {
ur = str.Join(ur, "#comments") ur = str.Join(path, "?", query)
} }
ur = str.Join(ur, "#comments")
return ur return ur
} }

View File

@ -6,7 +6,7 @@ import (
"github.com/fthvgb1/wp-go/app/plugins" "github.com/fthvgb1/wp-go/app/plugins"
"github.com/fthvgb1/wp-go/app/theme/wp" "github.com/fthvgb1/wp-go/app/theme/wp"
"github.com/fthvgb1/wp-go/app/theme/wp/components" "github.com/fthvgb1/wp-go/app/theme/wp/components"
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget" "github.com/fthvgb1/wp-go/app/theme/wp/middleware"
"github.com/fthvgb1/wp-go/app/wpconfig" "github.com/fthvgb1/wp-go/app/wpconfig"
"strings" "strings"
) )
@ -22,13 +22,7 @@ func configs(h *wp.Handle) {
return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`) return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`)
}) })
wp.InitPipe(h) wp.InitPipe(h)
h.PushHandler(constraints.PipeMiddleware, constraints.Home, middleware.CommonMiddleware(h)
wp.NewHandleFn(widget.CheckCategory, 100, "widget.CheckCategory"),
)
h.PushHandler(constraints.PipeMiddleware, constraints.Detail,
wp.NewHandleFn(wp.ShowPreComment, 100, "wp.ShowPreComment"),
)
h.Index.SetPageEle(plugins.TwentyFifteenPagination()) h.Index.SetPageEle(plugins.TwentyFifteenPagination())
h.PushCacheGroupHeadScript(constraints.AllScene, "CalCustomBackGround", 10.005, CalCustomBackGround) h.PushCacheGroupHeadScript(constraints.AllScene, "CalCustomBackGround", 10.005, CalCustomBackGround)
h.PushCacheGroupHeadScript(constraints.AllScene, "colorSchemeCss", 10.0056, colorSchemeCss) h.PushCacheGroupHeadScript(constraints.AllScene, "colorSchemeCss", 10.0056, colorSchemeCss)

View File

@ -10,7 +10,7 @@ import (
"github.com/fthvgb1/wp-go/app/plugins" "github.com/fthvgb1/wp-go/app/plugins"
"github.com/fthvgb1/wp-go/app/theme/wp" "github.com/fthvgb1/wp-go/app/theme/wp"
"github.com/fthvgb1/wp-go/app/theme/wp/components" "github.com/fthvgb1/wp-go/app/theme/wp/components"
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget" "github.com/fthvgb1/wp-go/app/theme/wp/middleware"
"github.com/fthvgb1/wp-go/app/wpconfig" "github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache/reload" "github.com/fthvgb1/wp-go/cache/reload"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
@ -51,11 +51,7 @@ func Hook(h *wp.Handle) {
func configs(h *wp.Handle) { func configs(h *wp.Handle) {
wp.InitPipe(h) wp.InitPipe(h)
h.PushHandler(constraints.PipeMiddleware, constraints.Home, middleware.CommonMiddleware(h)
wp.NewHandleFn(widget.CheckCategory, 100.006, "widget.CheckCategory"))
h.PushHandler(constraints.PipeMiddleware, constraints.Detail,
wp.NewHandleFn(wp.ShowPreComment, 100, "wp.ShowPreComment"),
)
h.AddActionFilter("bodyClass", calClass) h.AddActionFilter("bodyClass", calClass)
h.PushCacheGroupHeadScript(constraints.AllScene, "colorScheme-customHeader", 10, colorScheme, customHeader) h.PushCacheGroupHeadScript(constraints.AllScene, "colorScheme-customHeader", 10, colorScheme, customHeader)
components.WidgetArea(h) components.WidgetArea(h)

View File

@ -57,8 +57,8 @@ func (h *Handle) BodyClass() string {
author := h.Index.Param.Author author := h.Index.Param.Author
user, _ := cache.GetUserByName(h.C, author) user, _ := cache.GetUserByName(h.C, author)
class = append(class, str.Join("author-", number.IntToString(user.Id))) class = append(class, str.Join("author-", number.IntToString(user.Id)))
if user.UserLogin[0] != '%' { if user.DisplayName[0] != '%' {
class = append(class, str.Join("author-", user.UserLogin)) class = append(class, str.Join("author-", user.DisplayName))
} }
case constraints.Detail: case constraints.Detail:

View File

@ -12,7 +12,6 @@ import (
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/helper/tree" "github.com/fthvgb1/wp-go/helper/tree"
"net/http"
"strings" "strings"
) )
@ -235,39 +234,6 @@ func DropdownCategories(h *wp.Handle, args map[string]string, conf map[any]any,
return h.DoActionFilter("wp_dropdown_cats", s.String()) return h.DoActionFilter("wp_dropdown_cats", s.String())
} }
func CheckCategory(h *wp.Handle) {
name, ok := parseDropdownCate(h)
if ok {
h.C.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/p/category/%s", name))
h.Abort()
}
}
func parseDropdownCate(h *wp.Handle) (cateName string, r bool) {
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs())
name, ok := cate["{$name}"]
if !ok || name == "" {
return
}
cat := h.C.Query(name)
if cat == "" {
return
}
id := str.ToInteger[uint64](cat, 0)
if id < 1 {
return
}
i, cc := slice.SearchFirst(cache.CategoriesTags(h.C, constraints.Category), func(my models.TermsMy) bool {
return id == my.Terms.TermId
})
if i < 0 {
return
}
r = true
cateName = cc.Name
return
}
func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) { func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) {
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs()) cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs())
name, ok := cate["{$name}"] name, ok := cate["{$name}"]
@ -292,3 +258,12 @@ func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) {
category = cc category = cc
return return
} }
func CategoryQueryName(h *wp.Handle) string {
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs())
name, ok := cate["{$name}"]
if ok {
return name
}
return ""
}

View File

@ -14,7 +14,6 @@ import (
"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"
"strings" "strings"
"time" "time"
) )
@ -28,6 +27,7 @@ type DetailHandle struct {
Post models.Posts Post models.Posts
CommentPageEle pagination.Render CommentPageEle pagination.Render
TotalRaw int TotalRaw int
TotalPage int
} }
func NewDetailHandle(handle *Handle) *DetailHandle { func NewDetailHandle(handle *Handle) *DetailHandle {
@ -40,21 +40,11 @@ func (d *DetailHandle) BuildDetailData() (err error) {
if err != nil { if err != nil {
return return
} }
d.Comment() d.CommentData()
d.ContextPost() d.ContextPost()
return return
} }
func ShowPreComment(h *Handle) {
v, ok := cache.NewCommentCache().Get(h.C, h.C.Request.URL.RawQuery)
if ok {
h.C.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
h.C.Writer.WriteHeader(http.StatusOK)
_, _ = h.C.Writer.Write([]byte(v))
h.Abort()
}
}
func (d *DetailHandle) CheckAndGetPost() (err error) { func (d *DetailHandle) CheckAndGetPost() (err error) {
id := str.ToInteger[uint64](d.C.Param("id"), 0) id := str.ToInteger[uint64](d.C.Param("id"), 0)
maxId, err := cache.GetMaxPostId(d.C) maxId, err := cache.GetMaxPostId(d.C)
@ -88,7 +78,7 @@ func (d *DetailHandle) PasswordProject() {
} }
} }
} }
func (d *DetailHandle) Comment() { func (d *DetailHandle) CommentData() {
d.ginH["totalCommentNum"] = 0 d.ginH["totalCommentNum"] = 0
d.ginH["totalCommentPage"] = 1 d.ginH["totalCommentPage"] = 1
d.ginH["commentPageNav"] = "" d.ginH["commentPageNav"] = ""
@ -109,11 +99,11 @@ func (d *DetailHandle) Comment() {
d.SetErr(err) d.SetErr(err)
return return
} }
totalPage := number.DivideCeil(topNum, d.Limit) d.TotalPage = number.DivideCeil(topNum, d.Limit)
if !strings.Contains(d.C.Request.URL.Path, "comment-page") { if !strings.Contains(d.C.Request.URL.Path, "comment-page") {
defaultCommentsPage := wpconfig.GetOption("default_comments_page") defaultCommentsPage := wpconfig.GetOption("default_comments_page")
if order == "desc" && defaultCommentsPage == "oldest" || order == "asc" && defaultCommentsPage == "newest" { if order == "desc" && defaultCommentsPage == "oldest" || order == "asc" && defaultCommentsPage == "newest" {
d.C.AddParam("page", number.IntToString(totalPage)) d.C.AddParam("page", number.IntToString(d.TotalPage))
} }
} }
d.Page = str.ToInteger(d.C.Param("page"), 1) d.Page = str.ToInteger(d.C.Param("page"), 1)
@ -121,16 +111,17 @@ func (d *DetailHandle) Comment() {
var key string var key string
if pageComments != "1" { if pageComments != "1" {
key = number.IntToString(d.Post.Id) key = number.IntToString(d.Post.Id)
d.Limit = 0
} else { } else {
key = fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit) key = fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit)
} }
d.ginH["page_comments"] = pageComments d.ginH["page_comments"] = pageComments
d.ginH["totalCommentPage"] = totalPage d.ginH["totalCommentPage"] = d.TotalPage
if totalPage < d.Page { if d.TotalPage < d.Page {
d.SetErr(errors.New("curren page above total page")) d.SetErr(errors.New("curren page above total page"))
return return
} }
data, err := cachemanager.GetBy[[]uint64]("PostCommentsIds", d.C, key, time.Second, d.Post.Id, d.Page, d.Limit, topNum) data, err := cache.PostTopLevelCommentIds(d.C, d.Post.Id, d.Page, d.Limit, topNum, order, key)
if err != nil { if err != nil {
d.SetErr(err) d.SetErr(err)
return return
@ -163,7 +154,7 @@ func (d *DetailHandle) RenderComment() {
if d.CommentPageEle == nil { if d.CommentPageEle == nil {
d.CommentPageEle = plugins.TwentyFifteenCommentPagination() d.CommentPageEle = plugins.TwentyFifteenCommentPagination()
} }
if wpconfig.GetOption("page_comments") == "1" { if wpconfig.GetOption("page_comments") == "1" && d.TotalPage > 1 {
d.ginH["commentPageNav"] = pagination.Paginate(d.CommentPageEle, d.TotalRaw, d.Limit, d.Page, 1, *d.C.Request.URL, d.IsHttps()) d.ginH["commentPageNav"] = pagination.Paginate(d.CommentPageEle, d.TotalRaw, d.Limit, d.Page, 1, *d.C.Request.URL, d.IsHttps())
} }
} }

View File

@ -0,0 +1,154 @@
package middleware
import (
"github.com/fthvgb1/wp-go/app/pkg/cache"
"github.com/fthvgb1/wp-go/app/pkg/constraints"
"github.com/fthvgb1/wp-go/app/theme/wp"
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
"github.com/fthvgb1/wp-go/cache/reload"
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/number"
str "github.com/fthvgb1/wp-go/helper/strings"
"net/http"
"strconv"
"time"
)
var plainRouteParam = reload.Vars([]Plain{
{
Action: "p",
Param: map[string]string{
"p": "id",
"cpage": "page",
},
Scene: constraints.Detail,
},
{
Scene: constraints.Category,
Fn: func(h *wp.Handle) bool {
c, ok := widget.IsCategory(h)
if !ok {
return false
}
h.C.AddParam("category", c.Name)
h.C.AddParam("page", h.C.Query("paged"))
return true
},
},
{
Scene: constraints.Tag,
Action: "tag",
Param: map[string]string{
"tag": "tag",
"paged": "page",
},
},
{
Scene: constraints.Archive,
Fn: func(h *wp.Handle) bool {
m := h.C.Query("m")
if m == "" {
return false
}
t, err := time.Parse("200601", m)
if err != nil {
return false
}
h.C.AddParam("year", strconv.Itoa(t.Year()))
h.C.AddParam("month", number.IntToString(t.Month()))
h.C.AddParam("page", h.C.Query("paged"))
return true
},
},
{
Scene: constraints.Author,
Fn: func(h *wp.Handle) bool {
u := h.C.Query("author")
if u == "" {
return false
}
users := reload.GetAnyValBys("usersIds", struct{}{},
func(_ struct{}) (map[uint64]string, bool) {
users, err := cache.GetAllUsername(h.C)
if err != nil {
return nil, true
}
return maps.Flip(users), true
})
name, ok := users[str.ToInteger[uint64](u, 0)]
if !ok {
return false
}
h.C.AddParam("author", name)
h.C.AddParam("page", h.C.Query("paged"))
return true
},
},
})
func PushExplainRouteParam(explain ...Plain) {
v := plainRouteParam.Load()
v = append(v, explain...)
plainRouteParam.Store(v)
}
type Plain struct {
Action string
Param map[string]string
Scene string
Fn func(h *wp.Handle) bool
}
func MixWithPlain(h *wp.Handle) {
for _, explain := range plainRouteParam.Load() {
if explain.Action == "" && explain.Fn == nil {
continue
}
if explain.Fn != nil {
if !explain.Fn(h) {
continue
}
h.C.Set("inited", false)
if explain.Scene != "" {
h.SetScene(explain.Scene)
}
wp.Run(h, nil)
h.Abort()
return
}
if explain.Scene == "" {
continue
}
action := h.C.Query(explain.Action)
if action == "" {
continue
}
h.SetScene(explain.Scene)
for query, param := range explain.Param {
h.C.AddParam(param, h.C.Query(query))
}
h.C.Set("inited", false)
wp.Run(h, nil)
h.Abort()
return
}
}
func ShowPreComment(h *wp.Handle) {
v, ok := cache.NewCommentCache().Get(h.C, h.C.Request.URL.RawQuery)
if ok {
h.C.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
h.C.Writer.WriteHeader(http.StatusOK)
_, _ = h.C.Writer.Write([]byte(v))
h.Abort()
}
}
func CommonMiddleware(h *wp.Handle) {
h.PushHandler(constraints.PipeMiddleware, constraints.Home,
wp.NewHandleFn(MixWithPlain, 100, "middleware.MixWithPlain"),
)
h.PushHandler(constraints.PipeMiddleware, constraints.Detail,
wp.NewHandleFn(ShowPreComment, 100, "middleware.ShowPreComment"),
)
}

View File

@ -107,7 +107,10 @@ func Run(h *Handle, conf func(*Handle)) {
if !helper.GetContextVal(h.C, "inited", false) { if !helper.GetContextVal(h.C, "inited", false) {
InitHandle(conf, h) InitHandle(conf, h)
} }
reload.GetAnyValBys(str.Join("pipeInit-", h.scene), h, func(h *Handle) (func(*Handle), bool) { reload.GetAnyValBys(str.Join("pipeInit-", h.scene), h, BuildPipeAndHandler)(h)
}
func BuildPipeAndHandler(h *Handle) (func(*Handle), bool) {
p := GetFn[Pipe]("pipe", constraints.AllScene) p := GetFn[Pipe]("pipe", constraints.AllScene)
p = append(p, GetFn[Pipe]("pipe", h.scene)...) p = append(p, GetFn[Pipe]("pipe", h.scene)...)
pipes := slice.FilterAndMap(p, func(pipe Pipe) (Pipe, bool) { pipes := slice.FilterAndMap(p, func(pipe Pipe) (Pipe, bool) {
@ -130,7 +133,6 @@ func Run(h *Handle, conf func(*Handle)) {
return t.Fn return t.Fn
}) })
return HandlePipe(NothingToDo, arr...), true return HandlePipe(NothingToDo, arr...), true
})(h)
} }
func MiddlewareKey(h *Handle, pipScene string) string { func MiddlewareKey(h *Handle, pipScene string) string {

View File

@ -196,6 +196,10 @@ func GetAnyValBys[T, A any](namespace string, a A, fn func(A) (T, bool), args ..
return v.v return v.v
} }
// Vars get default value and whenever reloaded assign default value
//
// args same as Push
// if give a name, then can be flushed by calls FlushAnyVal
func Vars[T any](defaults T, args ...any) *safety.Var[T] { func Vars[T any](defaults T, args ...any) *safety.Var[T] {
ss := safety.NewVar(defaults) ss := safety.NewVar(defaults)
ord, name := parseArgs(args...) ord, name := parseArgs(args...)
@ -220,6 +224,11 @@ func parseArgs(a ...any) (ord float64, name string) {
} }
return ord, name return ord, name
} }
// VarsBy
//
// args same as Push
// if give a name, then can be flushed by calls FlushAnyVal
func VarsBy[T any](fn func() T, args ...any) *safety.Var[T] { func VarsBy[T any](fn func() T, args ...any) *safety.Var[T] {
ss := safety.NewVar(fn()) ss := safety.NewVar(fn())
ord, name := parseArgs(args...) ord, name := parseArgs(args...)
@ -252,6 +261,9 @@ func SafeMap[K comparable, T any](args ...any) *safety.Map[K, T] {
return m return m
} }
// Push the func that will be call whenever Reload called
//
// if give a name, then can be flushed by calls FlushAnyVal
func Push(fn func(), a ...any) { func Push(fn func(), a ...any) {
ord, name := parseArgs(a...) ord, name := parseArgs(a...)
calls.Append(queue{fn, ord, name}) calls.Append(queue{fn, ord, name})