diff --git a/app/pkg/cache/cache.go b/app/pkg/cache/cache.go index 1a15642..56c22ae 100644 --- a/app/pkg/cache/cache.go +++ b/app/pkg/cache/cache.go @@ -7,7 +7,6 @@ import ( "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" "github.com/fthvgb1/wp-go/safety" "time" ) @@ -78,7 +77,7 @@ func InitActionsCommonCache() { 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 }) @@ -88,7 +87,7 @@ func InitActionsCommonCache() { 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") @@ -125,30 +124,3 @@ func Archives(ctx context.Context) []models.PostArchive { } 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) -} diff --git a/app/pkg/cache/categoryandtag.go b/app/pkg/cache/categoryandtag.go new file mode 100644 index 0000000..b873161 --- /dev/null +++ b/app/pkg/cache/categoryandtag.go @@ -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) +} diff --git a/app/pkg/cache/comments.go b/app/pkg/cache/comments.go index be866d0..02b06de 100644 --- a/app/pkg/cache/comments.go +++ b/app/pkg/cache/comments.go @@ -9,11 +9,13 @@ import ( "github.com/fthvgb1/wp-go/app/wpconfig" "github.com/fthvgb1/wp-go/cache" "github.com/fthvgb1/wp-go/cache/cachemanager" + "github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/number" str "github.com/fthvgb1/wp-go/helper/strings" "time" ) +// RecentComments query func see RecentComment func RecentComments(ctx context.Context, n int) (r []models.Comments) { nn := number.Max(n, 10) 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 } -func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) { - ids, err := cachemanager.GetBy[[]uint64]("PostCommentsIds", ctx, Id, time.Second) - if err != nil { - return nil, err +// PostTopLevelCommentIds query func see PostTopComments +func PostTopLevelCommentIds(ctx context.Context, postId uint64, page, limit, total int, order string, a ...any) ([]uint64, error) { + var key string + 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) { 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) { 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) limit := a[2].(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 { 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) { - comment, err := cachemanager.GetBy[models.Comments]("postCommentData", ctx, commentId, time.Second) + comment, err := GetCommentById(ctx, commentId) if err != nil { return 0, err } diff --git a/app/pkg/cache/feed.go b/app/pkg/cache/feed.go index f44d22d..a433564 100644 --- a/app/pkg/cache/feed.go +++ b/app/pkg/cache/feed.go @@ -2,6 +2,7 @@ package cache import ( "context" + "errors" "fmt" "github.com/fthvgb1/wp-go/app/pkg/logs" "github.com/fthvgb1/wp-go/app/pkg/models" @@ -44,6 +45,7 @@ func FeedCache() *cache.VarCache[[]string] { return r } +// PostFeedCache query func see PostFeed func PostFeedCache() *cache.MapCache[string, string] { r, _ := cachemanager.GetMapCache[string, string]("postFeed") return r @@ -95,7 +97,7 @@ func feed(c context.Context, _ ...any) (xml []string, err error) { 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) maxId, err := GetMaxPostId(c) logs.IfError(err, "get max post id") @@ -107,11 +109,11 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) { return } 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 { return } - comments, err := cachemanager.GetBatchBy[models.Comments]("postCommentData", c, ids, time.Second) + comments, err := GetCommentDataByIds(c, ids) if err != nil { return } @@ -127,10 +129,14 @@ func postFeed(c context.Context, id string, _ ...any) (x string, err error) { wpposts.PasswdProjectContent(&post) if len(comments) > 0 { t := comments[len(comments)-1] + u, err := GetCommentUrl(c, t.CommentId, t.CommentPostId) + if err != nil { + return "", err + } rs.Items = []rss2.Item{ { 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, PubDate: t.CommentDateGmt.Format(timeFormat), 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 { 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{ 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, PubDate: t.CommentDateGmt.Format(timeFormat), 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 { 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{ Title: fmt.Sprintf("%s对《%s》的评论", t.CommentAuthor, post.PostTitle), - Link: t.CommentAuthorUrl, + Link: u, Creator: t.CommentAuthor, Description: desc, PubDate: t.CommentDateGmt.Format(timeFormat), diff --git a/app/pkg/cache/postmeta.go b/app/pkg/cache/postmeta.go index 1556911..99520e2 100644 --- a/app/pkg/cache/postmeta.go +++ b/app/pkg/cache/postmeta.go @@ -6,9 +6,12 @@ import ( "time" ) +// GetPostMetaByPostIds query func see dao.GetPostMetaByPostIds func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) { 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) { return cachemanager.GetBy[map[string]any]("postMetaData", ctx, id, time.Second) } diff --git a/app/pkg/cache/posts.go b/app/pkg/cache/posts.go index 023fcba..f0747ca 100644 --- a/app/pkg/cache/posts.go +++ b/app/pkg/cache/posts.go @@ -14,14 +14,17 @@ import ( "time" ) +// GetPostById query func see dao.GetPostsByIds func GetPostById(ctx context.Context, id uint64) (models.Posts, error) { 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) { 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) { ids, err := cachemanager.GetBy[dao.PostIds]("searchPostIds", ctx, key, time.Second, args...) if err != nil { @@ -32,6 +35,7 @@ func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts, return } +// PostLists query func see dao.SearchPostIds 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...) if err != nil { @@ -42,10 +46,12 @@ func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts, return } +// GetMaxPostId query func see dao.GetMaxPostId func GetMaxPostId(ctx context.Context) (uint64, error) { return cachemanager.GetVarVal[uint64]("maxPostId", ctx, time.Second) } +// RecentPosts query func see dao.RecentPosts func RecentPosts(ctx context.Context, n int) (r []models.Posts) { nn := n feedNum := str.ToInteger(wpconfig.GetOption("posts_per_rss"), 10) @@ -58,6 +64,7 @@ func RecentPosts(ctx context.Context, n int) (r []models.Posts) { return } +// GetContextPost query func see dao.GetPostContext 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) if err != nil { @@ -68,6 +75,7 @@ func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next 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) { res, err := cachemanager.GetBy[[]uint64]("monthPostIds", ctx, fmt.Sprintf("%s%s", year, month), time.Second, year, month) if err != nil { diff --git a/app/pkg/cache/users.go b/app/pkg/cache/users.go index fdf8438..0ba63e5 100644 --- a/app/pkg/cache/users.go +++ b/app/pkg/cache/users.go @@ -8,14 +8,17 @@ import ( "time" ) +// GetUserByName query func see dao.GetUserByName 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) { - return cachemanager.GetVarVal[map[string]struct{}]("allUsername", ctx, time.Second) +// GetAllUsername query func see dao.AllUsername +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 { r, err := cachemanager.GetBy[models.Users]("userData", ctx, uid, time.Second) logs.IfError(err, "get user", uid) diff --git a/app/pkg/dao/comments.go b/app/pkg/dao/comments.go index 24c203f..445b25a 100644 --- a/app/pkg/dao/comments.go +++ b/app/pkg/dao/comments.go @@ -114,9 +114,7 @@ func postTopCommentNumWhere(postId uint64) model.SqlBuilder { return 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") +func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, order string) ([]uint64, int, error) { condition := model.Conditions( model.Where(postTopCommentNumWhere(postId)), model.TotalRaw(totalRaw), @@ -129,7 +127,7 @@ func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw i var r []models.Comments var total int var err error - if pageComments != "1" { + if limit < 1 { r, err = model.ChunkFind[models.Comments](ctx, 300, condition) total = len(r) } else { diff --git a/app/pkg/dao/users.go b/app/pkg/dao/users.go index c0ebb6d..9dd9286 100644 --- a/app/pkg/dao/users.go +++ b/app/pkg/dao/users.go @@ -12,21 +12,21 @@ func GetUserById(ctx context.Context, uid uint64, _ ...any) (r models.Users, err 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{ {"user_status", "=", "0", "int"}, - }, "user_login") + }, "display_name,ID") if err != nil { return nil, err } - return slice.ToMap(r, func(t models.Users) (string, struct{}) { - return t.UserLogin, struct{}{} + return slice.ToMap(r, func(t models.Users) (string, uint64) { + return t.DisplayName, t.Id }, true), nil } func GetUserByName(ctx context.Context, u string, _ ...any) (r models.Users, err error) { r, err = model.FirstOne[models.Users](ctx, model.SqlBuilder{{ - "user_login", u, + "display_name", u, }}, "*", nil) return } diff --git a/app/plugins/pagination.go b/app/plugins/pagination.go index 7f32f19..764f2d7 100644 --- a/app/plugins/pagination.go +++ b/app/plugins/pagination.go @@ -7,6 +7,7 @@ import ( str "github.com/fthvgb1/wp-go/helper/strings" "net/url" "regexp" + "strconv" "strings" ) @@ -72,8 +73,20 @@ func (p PageEle) Middle(page int, url string) string { var reg = regexp.MustCompile(`(/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 { 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/") { 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 == "" { 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 { 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-") { - 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 = strings.Replace(path, "//", "/", -1) - ur := str.Join(path, query) - if !strings.Contains(ur, "#comments") { - ur = str.Join(ur, "#comments") + ur := path + if query != "" { + ur = str.Join(path, "?", query) } + ur = str.Join(ur, "#comments") return ur } diff --git a/app/theme/twentyfifteen/twentyfifteen.go b/app/theme/twentyfifteen/twentyfifteen.go index a10bf56..28bbb4c 100644 --- a/app/theme/twentyfifteen/twentyfifteen.go +++ b/app/theme/twentyfifteen/twentyfifteen.go @@ -6,7 +6,7 @@ import ( "github.com/fthvgb1/wp-go/app/plugins" "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/widget" + "github.com/fthvgb1/wp-go/app/theme/wp/middleware" "github.com/fthvgb1/wp-go/app/wpconfig" "strings" ) @@ -22,13 +22,7 @@ func configs(h *wp.Handle) { return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`) }) wp.InitPipe(h) - h.PushHandler(constraints.PipeMiddleware, constraints.Home, - wp.NewHandleFn(widget.CheckCategory, 100, "widget.CheckCategory"), - ) - h.PushHandler(constraints.PipeMiddleware, constraints.Detail, - wp.NewHandleFn(wp.ShowPreComment, 100, "wp.ShowPreComment"), - ) - + middleware.CommonMiddleware(h) h.Index.SetPageEle(plugins.TwentyFifteenPagination()) h.PushCacheGroupHeadScript(constraints.AllScene, "CalCustomBackGround", 10.005, CalCustomBackGround) h.PushCacheGroupHeadScript(constraints.AllScene, "colorSchemeCss", 10.0056, colorSchemeCss) diff --git a/app/theme/twentyseventeen/twentyseventeen.go b/app/theme/twentyseventeen/twentyseventeen.go index 86f6b12..1e24812 100644 --- a/app/theme/twentyseventeen/twentyseventeen.go +++ b/app/theme/twentyseventeen/twentyseventeen.go @@ -10,7 +10,7 @@ import ( "github.com/fthvgb1/wp-go/app/plugins" "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/widget" + "github.com/fthvgb1/wp-go/app/theme/wp/middleware" "github.com/fthvgb1/wp-go/app/wpconfig" "github.com/fthvgb1/wp-go/cache/reload" "github.com/fthvgb1/wp-go/helper" @@ -51,11 +51,7 @@ func Hook(h *wp.Handle) { func configs(h *wp.Handle) { wp.InitPipe(h) - h.PushHandler(constraints.PipeMiddleware, constraints.Home, - wp.NewHandleFn(widget.CheckCategory, 100.006, "widget.CheckCategory")) - h.PushHandler(constraints.PipeMiddleware, constraints.Detail, - wp.NewHandleFn(wp.ShowPreComment, 100, "wp.ShowPreComment"), - ) + middleware.CommonMiddleware(h) h.AddActionFilter("bodyClass", calClass) h.PushCacheGroupHeadScript(constraints.AllScene, "colorScheme-customHeader", 10, colorScheme, customHeader) components.WidgetArea(h) diff --git a/app/theme/wp/calclass.go b/app/theme/wp/calclass.go index 91c372e..e3a6984 100644 --- a/app/theme/wp/calclass.go +++ b/app/theme/wp/calclass.go @@ -57,8 +57,8 @@ func (h *Handle) BodyClass() string { author := h.Index.Param.Author user, _ := cache.GetUserByName(h.C, author) class = append(class, str.Join("author-", number.IntToString(user.Id))) - if user.UserLogin[0] != '%' { - class = append(class, str.Join("author-", user.UserLogin)) + if user.DisplayName[0] != '%' { + class = append(class, str.Join("author-", user.DisplayName)) } case constraints.Detail: diff --git a/app/theme/wp/components/widget/category.go b/app/theme/wp/components/widget/category.go index 1e8a24e..cff1fd4 100644 --- a/app/theme/wp/components/widget/category.go +++ b/app/theme/wp/components/widget/category.go @@ -12,7 +12,6 @@ import ( "github.com/fthvgb1/wp-go/helper/slice" str "github.com/fthvgb1/wp-go/helper/strings" "github.com/fthvgb1/wp-go/helper/tree" - "net/http" "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()) } -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) { cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs()) name, ok := cate["{$name}"] @@ -292,3 +258,12 @@ func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) { category = cc 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 "" +} diff --git a/app/theme/wp/detail.go b/app/theme/wp/detail.go index 4a93bea..08265df 100644 --- a/app/theme/wp/detail.go +++ b/app/theme/wp/detail.go @@ -14,7 +14,6 @@ import ( "github.com/fthvgb1/wp-go/helper/number" str "github.com/fthvgb1/wp-go/helper/strings" "github.com/fthvgb1/wp-go/plugin/pagination" - "net/http" "strings" "time" ) @@ -28,6 +27,7 @@ type DetailHandle struct { Post models.Posts CommentPageEle pagination.Render TotalRaw int + TotalPage int } func NewDetailHandle(handle *Handle) *DetailHandle { @@ -40,21 +40,11 @@ func (d *DetailHandle) BuildDetailData() (err error) { if err != nil { return } - d.Comment() + d.CommentData() d.ContextPost() 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) { id := str.ToInteger[uint64](d.C.Param("id"), 0) 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["totalCommentPage"] = 1 d.ginH["commentPageNav"] = "" @@ -109,11 +99,11 @@ func (d *DetailHandle) Comment() { d.SetErr(err) return } - totalPage := number.DivideCeil(topNum, d.Limit) + d.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.C.AddParam("page", number.IntToString(d.TotalPage)) } } d.Page = str.ToInteger(d.C.Param("page"), 1) @@ -121,16 +111,17 @@ func (d *DetailHandle) Comment() { var key string if pageComments != "1" { key = number.IntToString(d.Post.Id) + d.Limit = 0 } else { key = fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit) } d.ginH["page_comments"] = pageComments - d.ginH["totalCommentPage"] = totalPage - if totalPage < d.Page { + d.ginH["totalCommentPage"] = d.TotalPage + if d.TotalPage < d.Page { d.SetErr(errors.New("curren page above total page")) 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 { d.SetErr(err) return @@ -163,7 +154,7 @@ func (d *DetailHandle) RenderComment() { if d.CommentPageEle == nil { 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()) } } diff --git a/app/theme/wp/middleware/middleware.go b/app/theme/wp/middleware/middleware.go new file mode 100644 index 0000000..6bc2631 --- /dev/null +++ b/app/theme/wp/middleware/middleware.go @@ -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"), + ) +} diff --git a/app/theme/wp/pipe.go b/app/theme/wp/pipe.go index 5b6d457..b43498e 100644 --- a/app/theme/wp/pipe.go +++ b/app/theme/wp/pipe.go @@ -107,30 +107,32 @@ func Run(h *Handle, conf func(*Handle)) { if !helper.GetContextVal(h.C, "inited", false) { InitHandle(conf, h) } - reload.GetAnyValBys(str.Join("pipeInit-", h.scene), h, func(h *Handle) (func(*Handle), bool) { - p := GetFn[Pipe]("pipe", constraints.AllScene) - p = append(p, GetFn[Pipe]("pipe", h.scene)...) - pipes := slice.FilterAndMap(p, func(pipe Pipe) (Pipe, bool) { - var ok bool - hooks := GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", constraints.AllScene) - hooks = append(hooks, GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", h.scene)...) - for _, fn := range hooks { - pipe, ok = fn(pipe) - if !ok { - return pipe, false - } - } - return pipe, pipe.Fn != nil - }) - slice.SimpleSort(pipes, slice.DESC, func(t Pipe) float64 { - return t.Order - }) + reload.GetAnyValBys(str.Join("pipeInit-", h.scene), h, BuildPipeAndHandler)(h) +} - arr := slice.Map(pipes, func(t Pipe) HandlePipeFn[*Handle] { - return t.Fn - }) - return HandlePipe(NothingToDo, arr...), true - })(h) +func BuildPipeAndHandler(h *Handle) (func(*Handle), bool) { + p := GetFn[Pipe]("pipe", constraints.AllScene) + p = append(p, GetFn[Pipe]("pipe", h.scene)...) + pipes := slice.FilterAndMap(p, func(pipe Pipe) (Pipe, bool) { + var ok bool + hooks := GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", constraints.AllScene) + hooks = append(hooks, GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", h.scene)...) + for _, fn := range hooks { + pipe, ok = fn(pipe) + if !ok { + return pipe, false + } + } + return pipe, pipe.Fn != nil + }) + slice.SimpleSort(pipes, slice.DESC, func(t Pipe) float64 { + return t.Order + }) + + arr := slice.Map(pipes, func(t Pipe) HandlePipeFn[*Handle] { + return t.Fn + }) + return HandlePipe(NothingToDo, arr...), true } func MiddlewareKey(h *Handle, pipScene string) string { diff --git a/cache/reload/reload.go b/cache/reload/reload.go index a16a741..39615d9 100644 --- a/cache/reload/reload.go +++ b/cache/reload/reload.go @@ -196,6 +196,10 @@ func GetAnyValBys[T, A any](namespace string, a A, fn func(A) (T, bool), args .. 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] { ss := safety.NewVar(defaults) ord, name := parseArgs(args...) @@ -220,6 +224,11 @@ func parseArgs(a ...any) (ord float64, name string) { } 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] { ss := safety.NewVar(fn()) ord, name := parseArgs(args...) @@ -252,6 +261,9 @@ func SafeMap[K comparable, T any](args ...any) *safety.Map[K, T] { 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) { ord, name := parseArgs(a...) calls.Append(queue{fn, ord, name})