package actions import ( "fmt" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "github/fthvgb1/wp-go/helper" cache2 "github/fthvgb1/wp-go/internal/pkg/cache" dao "github/fthvgb1/wp-go/internal/pkg/dao" "github/fthvgb1/wp-go/internal/pkg/models" "github/fthvgb1/wp-go/internal/plugins" "github/fthvgb1/wp-go/internal/templates" "github/fthvgb1/wp-go/internal/wpconfig" "github/fthvgb1/wp-go/model" "math" "net/http" "regexp" "strconv" "strings" "sync/atomic" ) type indexHandle struct { c *gin.Context session sessions.Session page int pageSize int title string titleL string titleR string search string author string totalPage int category string categoryType string where model.SqlBuilder orderBy string order string join model.SqlBuilder postType []any status []any header string paginationStep int scene uint } func newIndexHandle(ctx *gin.Context) *indexHandle { size := wpconfig.Options.Value("posts_per_page") si, _ := strconv.Atoi(size) return &indexHandle{ c: ctx, session: sessions.Default(ctx), page: 1, pageSize: si, paginationStep: 1, titleL: wpconfig.Options.Value("blogname"), titleR: wpconfig.Options.Value("blogdescription"), where: model.SqlBuilder{ {"post_type", "in", ""}, {"post_status", "in", ""}, }, orderBy: "post_date", join: model.SqlBuilder{}, postType: []any{"post"}, status: []any{"publish"}, scene: plugins.Home, } } func (h *indexHandle) setTitleLR(l, r string) { h.titleL = l h.titleR = r } func (h *indexHandle) getTitle() string { h.title = fmt.Sprintf("%s-%s", h.titleL, h.titleR) return h.title } func (h *indexHandle) getSearchKey() string { return fmt.Sprintf("action:%s|%s|%s|%s|%s|%s|%d|%d", h.author, h.search, h.orderBy, h.order, h.category, h.categoryType, h.page, h.pageSize) } func (h *indexHandle) parseParams() (err error) { h.order = h.c.Query("order") if !helper.IsContainInArr(h.order, []string{"asc", "desc"}) { h.order = "asc" } year := h.c.Param("year") if year != "" { h.where = append(h.where, []string{ "year(post_date)", year, }) } month := h.c.Param("month") if month != "" { h.where = append(h.where, []string{ "month(post_date)", month, }) ss := fmt.Sprintf("%s年%s月", year, strings.TrimLeft(month, "0")) h.header = fmt.Sprintf("月度归档: %s", ss) h.setTitleLR(ss, wpconfig.Options.Value("blogname")) h.scene = plugins.Archive } category := h.c.Param("category") if category == "" { category = h.c.Param("tag") if category != "" { h.categoryType = "post_tag" h.header = fmt.Sprintf("标签: %s", category) } } else { h.categoryType = "category" h.header = fmt.Sprintf("分类: %s", category) } h.category = category username := h.c.Param("author") if username != "" { user, er := cache2.GetUserByName(h.c, username) if er != nil { err = er return } h.author = username h.where = append(h.where, []string{ "post_author", "=", strconv.FormatUint(user.Id, 10), "int", }) } if category != "" { h.where = append(h.where, []string{ "d.name", category, }, []string{"taxonomy", h.categoryType}) h.join = append(h.join, []string{ "a", "left join", "wp_term_relationships b", "a.Id=b.object_id", }, []string{ "left join", "wp_term_taxonomy c", "b.term_taxonomy_id=c.term_taxonomy_id", }, []string{ "left join", "wp_terms d", "c.term_id=d.term_id", }) h.setTitleLR(category, wpconfig.Options.Value("blogname")) h.scene = plugins.Category } s := h.c.Query("s") if s != "" && strings.Replace(s, " ", "", -1) != "" { q := helper.StrJoin("%", s, "%") h.where = append(h.where, []string{ "and", "post_title", "like", q, "", "or", "post_content", "like", q, "", "or", "post_excerpt", "like", q, "", }, []string{"post_password", ""}) h.postType = append(h.postType, "page", "attachment") h.header = fmt.Sprintf("%s的搜索结果", s) h.setTitleLR(helper.StrJoin(`"`, s, `"`, "的搜索结果"), wpconfig.Options.Value("blogname")) h.search = s h.scene = plugins.Search } p := h.c.Query("paged") if p == "" { p = h.c.Param("page") } if p != "" { if pa, err := strconv.Atoi(p); err == nil { h.page = pa } } total := int(atomic.LoadInt64(&dao.TotalRaw)) if total > 0 && total < (h.page-1)*h.pageSize { h.page = 1 } if h.page > 1 && (h.category != "" || h.search != "" || month != "") { h.setTitleLR(fmt.Sprintf("%s-第%d页", h.titleL, h.page), wpconfig.Options.Value("blogname")) } return } func (h *indexHandle) getTotalPage(totalRaws int) int { h.totalPage = int(math.Ceil(float64(totalRaws) / float64(h.pageSize))) return h.totalPage } func Index(c *gin.Context) { h := newIndexHandle(c) var postIds []models.Posts var totalRaw int var err error archive := cache2.Archives(c) recent := cache2.RecentPosts(c, 5) categoryItems := cache2.Categories(c) recentComments := cache2.RecentComments(c, 5) ginH := gin.H{ "options": wpconfig.Options, "recentPosts": recent, "archives": archive, "categories": categoryItems, "search": h.search, "header": h.header, "recentComments": recentComments, } defer func() { stat := http.StatusOK if err != nil { c.Error(err) stat = http.StatusInternalServerError return } c.HTML(stat, helper.StrJoin(getTemplateName(), "/posts/index.gohtml"), ginH) }() err = h.parseParams() if err != nil { return } ginH["title"] = h.getTitle() if c.Param("month") != "" { postIds, totalRaw, err = cache2.GetMonthPostIds(c, c.Param("year"), c.Param("month"), h.page, h.pageSize, h.order) if err != nil { return } } else if h.search != "" { postIds, totalRaw, err = cache2.SearchPost(c, h.getSearchKey(), c, h.where, h.page, h.pageSize, model.SqlBuilder{{h.orderBy, h.order}}, h.join, h.postType, h.status) } else { postIds, totalRaw, err = cache2.PostLists(c, h.getSearchKey(), c, h.where, h.page, h.pageSize, model.SqlBuilder{{h.orderBy, h.order}}, h.join, h.postType, h.status) } if err != nil { return } if len(postIds) < 1 && h.category != "" { h.titleL = "未找到页面" } pw := h.session.Get("post_password") plug := plugins.NewPostPlugin(c, h.scene) for i, post := range postIds { plugins.PasswordProjectTitle(&postIds[i]) if post.PostPassword != "" && pw != post.PostPassword { plugins.PasswdProjectContent(&postIds[i]) } else { plugins.ApplyPlugin(plug, &postIds[i]) } } for i, post := range recent { if post.PostPassword != "" && pw != post.PostPassword { plugins.PasswdProjectContent(&recent[i]) } } q := c.Request.URL.Query().Encode() if q != "" { q = fmt.Sprintf("?%s", q) } ginH["posts"] = postIds ginH["totalPage"] = h.getTotalPage(totalRaw) ginH["pagination"] = pagination(h.page, h.totalPage, h.paginationStep, c.Request.URL.Path, q) ginH["title"] = h.getTitle() } var complie = regexp.MustCompile(`(/page)/(\d+)`) type PaginationElements struct { Prev string Next string } func getTemplateName() string { tmlp := wpconfig.Options.Value("template") if i, err := templates.IsTemplateIsExist(tmlp); err != nil || !i { tmlp = "twentyfifteen" } return tmlp } var page = map[string]PaginationElements{ "twentyfifteen": { Prev: "上一页", Next: "下一页", }, "twentyseventeen": { Prev: ` 上一页 `, Next: ` 下一页 `, }, } func pagination(currentPage, totalPage, step int, path, query string) (html string) { if totalPage < 2 { return } pathx := path if !strings.Contains(path, "/page/") { pathx = fmt.Sprintf("%s%s", path, "/page/1") } s := strings.Builder{} if currentPage > totalPage { currentPage = totalPage } r := complie start := currentPage - step end := currentPage + step if start < 1 { start = 1 } if currentPage > 1 { pp := "" if currentPage >= 2 { pp = replacePage(r, pathx, currentPage-1) } s.WriteString(fmt.Sprintf(``, pp, query, page[getTemplateName()].Prev)) } if currentPage >= step+2 { d := "" if currentPage > step+2 { d = `` } e := replacePage(r, path, 1) s.WriteString(fmt.Sprintf(` 1 %s `, e, query, d)) } if totalPage < end { end = totalPage } for page := start; page <= end; page++ { h := "" if currentPage == page { h = fmt.Sprintf(` %d `, page) } else { d := replacePage(r, pathx, page) h = fmt.Sprintf(` %d `, d, query, page) } s.WriteString(h) } if totalPage >= currentPage+step+1 { if totalPage > currentPage+step+1 { s.WriteString(``) } dd := replacePage(r, pathx, totalPage) s.WriteString(fmt.Sprintf(` %d`, dd, query, totalPage)) } if currentPage < totalPage { dd := replacePage(r, pathx, currentPage+1) s.WriteString(fmt.Sprintf(``, dd, query, page[getTemplateName()].Next)) } html = s.String() return } func replacePage(r *regexp.Regexp, path string, page int) (src string) { if page == 1 { src = r.ReplaceAllString(path, "") } else { s := fmt.Sprintf("$1/%d", page) src = r.ReplaceAllString(path, s) } src = strings.Replace(src, "//", "/", -1) if src == "" { src = "/" } return }