wp-go/actions/index.go
2022-12-28 14:24:59 +08:00

340 lines
9.1 KiB
Go

package actions
import (
"fmt"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github/fthvgb1/wp-go/actions/common"
"github/fthvgb1/wp-go/config/wpconfig"
"github/fthvgb1/wp-go/helper"
"github/fthvgb1/wp-go/models"
"github/fthvgb1/wp-go/models/wp"
"github/fthvgb1/wp-go/plugins"
"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 models.SqlBuilder
orderBy string
order string
join models.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: models.SqlBuilder{
{"post_type", "in", ""},
{"post_status", "in", ""},
},
orderBy: "post_date",
join: models.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("月度归档: <span>%s</span>", 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("标签: <span>%s</span>", category)
}
} else {
h.categoryType = "category"
h.header = fmt.Sprintf("分类: <span>%s</span>", category)
}
h.category = category
username := h.c.Param("author")
if username != "" {
user, er := common.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(&common.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 []wp.Posts
var totalRaw int
var err error
archive := common.Archives(c)
recent := common.RecentPosts(c, 5)
categoryItems := common.Categories(c)
recentComments := common.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
}
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 = common.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 = common.SearchPost(c, h.getSearchKey(), c, h.where, h.page, h.pageSize, models.SqlBuilder{{h.orderBy, h.order}}, h.join, h.postType, h.status)
} else {
postIds, totalRaw, err = common.PostLists(c, h.getSearchKey(), c, h.where, h.page, h.pageSize, models.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 {
common.PasswordProjectTitle(&postIds[i])
if post.PostPassword != "" && pw != post.PostPassword {
common.PasswdProjectContent(&postIds[i])
} else {
plugins.ApplyPlugin(plug, &postIds[i])
}
}
for i, post := range recent {
if post.PostPassword != "" && pw != post.PostPassword {
common.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(`<a class="prev page-numbers" href="%s%s">上一页</a>`, pp, query))
}
if currentPage >= step+2 {
d := ""
if currentPage > step+2 {
d = `<span class="page-numbers dots">…</span>`
}
e := replacePage(r, path, 1)
s.WriteString(fmt.Sprintf(`
<a class="page-numbers" href="%s%s"><span class="meta-nav screen-reader-text">页 </span>1</a>
%s
`, e, query, d))
}
if totalPage < end {
end = totalPage
}
for page := start; page <= end; page++ {
h := ""
if currentPage == page {
h = fmt.Sprintf(`
<span aria-current="page" class="page-numbers current">
<span class="meta-nav screen-reader-text">页 </span>%d</span>
`, page)
} else {
d := replacePage(r, pathx, page)
h = fmt.Sprintf(`
<a class="page-numbers" href="%s%s">
<span class="meta-nav screen-reader-text">页 </span>%d</a>
`, d, query, page)
}
s.WriteString(h)
}
if totalPage >= currentPage+step+1 {
if totalPage > currentPage+step+1 {
s.WriteString(`<span class="page-numbers dots">…</span>`)
}
dd := replacePage(r, pathx, totalPage)
s.WriteString(fmt.Sprintf(`
<a class="page-numbers" href="%s%s"><span class="meta-nav screen-reader-text">页 </span>%d</a>`, dd, query, totalPage))
}
if currentPage < totalPage {
dd := replacePage(r, pathx, currentPage+1)
s.WriteString(fmt.Sprintf(`<a class="next page-numbers" href="%s%s">下一页</a>`, 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
}