package actions
import (
"fmt"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github/fthvgb1/wp-go/helper"
"github/fthvgb1/wp-go/internal/cache"
dao "github/fthvgb1/wp-go/internal/dao"
"github/fthvgb1/wp-go/internal/models"
"github/fthvgb1/wp-go/internal/plugins"
"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 := cache.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 := cache.Archives(c)
recent := cache.RecentPosts(c, 5)
categoryItems := cache.Categories(c)
recentComments := cache.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(wpconfig.Options.Value("template"), "/posts/index.gohtml"), ginH)
}()
err = h.parseParams()
if err != nil {
return
}
ginH["title"] = h.getTitle()
if c.Param("month") != "" {
postIds, totalRaw, err = cache.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 = cache.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 = cache.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+)`)
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))
}
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))
}
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
}