优化代码,实现新的插件机制

This commit is contained in:
xing 2023-02-08 23:49:48 +08:00
parent f0028e72f4
commit 439a49cf12
13 changed files with 208 additions and 150 deletions

View File

@ -66,6 +66,13 @@ func Reduce[R, T any](arr []T, fn func(T, R) R, r R) R {
return r
}
func ReverseReduce[R, T any](a []T, fn func(T, R) R, r R) R {
for i := len(a) - 1; i >= 0; i-- {
r = fn(a[i], r)
}
return r
}
func Reverse[T any](arr []T) []T {
var r = make([]T, 0, len(arr))
for i := len(arr); i > 0; i-- {

View File

@ -840,3 +840,36 @@ func TestShift(t *testing.T) {
})
}
}
func TestReverseReduce(t *testing.T) {
type args[T int, R string] struct {
a []T
fn func(T, R) R
r R
}
type testCase[T int, R string] struct {
name string
args args[T, R]
want R
}
tests := []testCase[int, string]{
{
name: "t1",
args: args[int, string]{
a: number.Range(1, 10, 1),
fn: func(i int, r string) string {
return fmt.Sprintf("%s%d", r, i)
},
r: "",
},
want: "10987654321",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ReverseReduce(tt.args.a, tt.args.fn, tt.args.r); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ReverseReduce() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -29,10 +29,8 @@ func SortSelf[T any](arr []T, fn func(i, j T) bool) {
}
func Sort[T any](arr []T, fn func(i, j T) bool) (r []T) {
r = make([]T, 0, len(arr))
for _, t := range arr {
r = append(r, t)
}
r = make([]T, len(arr))
copy(r, arr)
slice := anyArr[T]{
data: r,
fn: fn,

View File

@ -8,6 +8,7 @@ import (
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins"
"github.com/fthvgb1/wp-go/internal/theme"
"github.com/fthvgb1/wp-go/internal/theme/common"
"github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
@ -31,6 +32,8 @@ func Detail(c *gin.Context) {
}
isApproveComment := false
status := plugins.Ok
pw := sessions.Default(c).Get("post_password")
defer func() {
code := http.StatusOK
if err != nil {
@ -44,7 +47,14 @@ func Detail(c *gin.Context) {
}
t := theme.GetTemplateName()
theme.Hook(t, code, c, ginH, plugins.Detail, status)
theme.Hook(t, common.Handle{
C: c,
GinH: ginH,
Password: "",
Scene: plugins.Detail,
Code: code,
Stats: status,
})
}()
ID := str.ToInteger[uint64](c.Param("id"), 0)
@ -57,7 +67,6 @@ func Detail(c *gin.Context) {
if post.Id == 0 || err != nil || post.PostStatus != "publish" {
return
}
pw := sessions.Default(c).Get("post_password")
showComment := false
if post.CommentCount > 0 || post.CommentStatus == "open" {
showComment = true
@ -77,7 +86,6 @@ func Detail(c *gin.Context) {
isApproveComment = true
return
}
plugins.ApplyPlugin(plugins.NewPostPlugin(c, plugins.Detail), &post)
comments, err := cache.PostComments(c, post.Id)
logs.ErrPrintln(err, "get post comment", post.Id)
ginH["comments"] = comments

View File

@ -27,7 +27,9 @@ func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
func Feed(c *gin.Context) {
if !isCacheExpired(c, cache.FeedCache().GetLastSetTime()) {
c.Status(http.StatusNotModified)
} else {
return
}
r, err := cache.FeedCache().GetCache(c, time.Second, c)
if err != nil {
c.Status(http.StatusInternalServerError)
@ -36,7 +38,6 @@ func Feed(c *gin.Context) {
return
}
setFeed(r[0], c, cache.FeedCache().GetLastSetTime())
}
}
func setFeed(s string, c *gin.Context, t time.Time) {
@ -52,7 +53,8 @@ func PostFeed(c *gin.Context) {
id := c.Param("id")
if !isCacheExpired(c, cache.PostFeedCache().GetLastSetTime(c, id)) {
c.Status(http.StatusNotModified)
} else {
return
}
s, err := cache.PostFeedCache().GetCache(c, id, time.Second, c, id)
if err != nil {
c.Status(http.StatusInternalServerError)
@ -61,13 +63,13 @@ func PostFeed(c *gin.Context) {
return
}
setFeed(s, c, cache.PostFeedCache().GetLastSetTime(c, id))
}
}
func CommentsFeed(c *gin.Context) {
if !isCacheExpired(c, cache.CommentsFeedCache().GetLastSetTime()) {
c.Status(http.StatusNotModified)
} else {
return
}
r, err := cache.CommentsFeedCache().GetCache(c, time.Second, c)
if err != nil {
c.Status(http.StatusInternalServerError)
@ -76,5 +78,4 @@ func CommentsFeed(c *gin.Context) {
return
}
setFeed(r[0], c, cache.CommentsFeedCache().GetLastSetTime())
}
}

View File

@ -14,6 +14,7 @@ import (
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins"
"github.com/fthvgb1/wp-go/internal/theme"
"github.com/fthvgb1/wp-go/internal/theme/common"
"github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/fthvgb1/wp-go/model"
"github.com/fthvgb1/wp-go/plugin/pagination"
@ -49,7 +50,7 @@ type indexHandle struct {
header string
paginationStep int
scene int
status int
stats int
}
func newIndexHandle(ctx *gin.Context) *indexHandle {
@ -71,7 +72,7 @@ func newIndexHandle(ctx *gin.Context) *indexHandle {
postType: []any{"post"},
postStatus: []any{"publish"},
scene: plugins.Home,
status: plugins.Ok,
stats: plugins.Ok,
}
}
@ -233,20 +234,32 @@ func Index(c *gin.Context) {
"recentComments": recentComments,
"posts": posts,
}
pw := h.session.Get("post_password")
pws, ok := pw.(string)
if !ok {
pws = ""
}
defer func() {
code := http.StatusOK
if err != nil {
code = http.StatusNotFound
if h.status == plugins.InternalErr {
if h.stats == plugins.InternalErr {
code = http.StatusInternalServerError
c.Error(err)
return
}
c.Error(err)
h.status = plugins.Error
h.stats = plugins.Error
}
t := theme.GetTemplateName()
theme.Hook(t, code, c, ginH, h.scene, h.status)
theme.Hook(t, common.Handle{
C: c,
GinH: ginH,
Password: pws,
Scene: h.scene,
Code: code,
Stats: h.stats,
})
}()
err = h.parseParams()
if err != nil {
@ -264,29 +277,15 @@ func Index(c *gin.Context) {
posts, 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.postStatus)
}
if err != nil {
h.status = plugins.Error
h.stats = plugins.Error
logs.ErrPrintln(err, "获取数据错误")
return
}
if len(posts) < 1 && h.category != "" {
h.titleL = "未找到页面"
h.status = plugins.Empty404
h.stats = plugins.Empty404
}
pw := h.session.Get("post_password")
plug := plugins.NewPostPlugin(c, h.scene)
for i, post := range posts {
if post.PostPassword != "" {
plugins.PasswordProjectTitle(&posts[i])
if pw != post.PostPassword {
plugins.PasswdProjectContent(&posts[i])
}
} else {
plugins.ApplyPlugin(plug, &posts[i])
}
}
q := c.Request.URL.Query().Encode()
if q != "" {
q = fmt.Sprintf("?%s", q)

View File

@ -25,7 +25,7 @@ func InitFeed() {
AtomLink: fmt.Sprintf("%s/feed", wpconfig.Options.Value("home")),
Link: wpconfig.Options.Value("siteurl"),
Description: wpconfig.Options.Value("blogdescription"),
Language: "zh-CN",
Language: wpconfig.GetLang(),
UpdatePeriod: "hourly",
UpdateFrequency: 1,
Generator: wpconfig.Options.Value("home"),

View File

@ -7,7 +7,6 @@ import (
"github.com/fthvgb1/wp-go/internal/pkg/config"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/plugin/digest"
"github.com/gin-gonic/gin"
"strings"
"time"
)
@ -30,7 +29,7 @@ func FlushCache() {
func digestRaw(arg ...any) (string, error) {
str := arg[0].(string)
id := arg[1].(uint64)
limit := config.GetConfig().DigestWordCount
limit := arg[2].(int)
if limit < 0 {
return str, nil
} else if limit == 0 {
@ -39,20 +38,11 @@ func digestRaw(arg ...any) (string, error) {
return digest.Raw(str, limit, fmt.Sprintf("/p/%d", id)), nil
}
func Digest(p *Plugin[models.Posts], c *gin.Context, post *models.Posts, scene int) {
if scene == Detail {
return
}
if post.PostExcerpt != "" {
func Digest(ctx context.Context, post *models.Posts, limit int) {
content, _ := digestCache.GetCache(ctx, post.Id, time.Second, post.PostContent, post.Id, limit)
post.PostContent = content
}
func PostExcerpt(post *models.Posts) {
post.PostContent = strings.Replace(post.PostExcerpt, "\n", "<br/>", -1)
} else {
post.PostContent = DigestCache(c, post.Id, post.PostContent)
}
p.Next()
}
func DigestCache(ctx *gin.Context, id uint64, str string) string {
content, _ := digestCache.GetCache(ctx, id, time.Second, str, id)
return content
}

View File

@ -35,18 +35,3 @@ type Plugin[T any] struct {
scene int
c *gin.Context
}
func NewPlugin[T any](calls []Func[T], index int, post *T, scene int, c *gin.Context) *Plugin[T] {
return &Plugin[T]{calls: calls, index: index, post: post, scene: scene, c: c}
}
func (p *Plugin[T]) Push(call ...Func[T]) {
p.calls = append(p.calls, call...)
}
func (p *Plugin[T]) Next() {
p.index++
for ; p.index < len(p.calls); p.index++ {
p.calls[p.index](p, p.c, p.post, p.scene)
}
}

View File

@ -3,21 +3,8 @@ package plugins
import (
"fmt"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/gin-gonic/gin"
)
func NewPostPlugin(ctx *gin.Context, scene int) *Plugin[models.Posts] {
p := NewPlugin[models.Posts](nil, -1, nil, scene, ctx)
p.Push(Digest)
return p
}
func ApplyPlugin(p *Plugin[models.Posts], post *models.Posts) {
p.post = post
p.Next()
p.index = -1
}
func PasswordProjectTitle(post *models.Posts) {
post.PostTitle = fmt.Sprintf("密码保护:%s", post.PostTitle)
}

View File

@ -0,0 +1,55 @@
package common
import (
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/pkg/config"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins"
"github.com/gin-gonic/gin"
)
type Handle struct {
C *gin.Context
GinH gin.H
Password string
Scene int
Code int
Stats int
}
type Fn[T any] func(T) T
type Plugin[T any] func(next Fn[T], h Handle, t T) T
func PluginFn[T any](a []Plugin[T], h Handle, fn Fn[T]) Fn[T] {
return slice.ReverseReduce(a, func(next Plugin[T], forward Fn[T]) Fn[T] {
return func(t T) T {
return next(forward, h, t)
}
}, fn)
}
func Default[T any](t T) T {
return t
}
func PasswordProject(next Fn[models.Posts], h Handle, post models.Posts) (r models.Posts) {
r = post
if post.PostPassword != "" {
plugins.PasswordProjectTitle(&r)
if h.Password != post.PostPassword {
plugins.PasswdProjectContent(&r)
return
}
}
r = next(r)
return
}
func Digest(next Fn[models.Posts], h Handle, post models.Posts) models.Posts {
if post.PostExcerpt != "" {
plugins.PostExcerpt(&post)
} else {
plugins.Digest(h.C, &post, config.GetConfig().DigestWordCount)
}
return next(post)
}

View File

@ -1,30 +1,25 @@
package theme
import (
"errors"
"github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins"
"github.com/fthvgb1/wp-go/plugin/pagination"
"github.com/gin-gonic/gin"
"github.com/fthvgb1/wp-go/internal/theme/common"
)
var themeMap = map[string]func(int, *gin.Context, gin.H, int, int){}
var themeMap = map[string]func(handle common.Handle){}
func addThemeHookFunc(name string, fn func(int, *gin.Context, gin.H, int, int)) {
func addThemeHookFunc(name string, fn func(handle common.Handle)) {
if _, ok := themeMap[name]; ok {
panic("exists same name theme")
}
themeMap[name] = fn
}
func Hook(themeName string, code int, c *gin.Context, h gin.H, scene, status int) {
func Hook(themeName string, handle common.Handle) {
fn, ok := themeMap[themeName]
if ok && fn != nil {
fn(code, c, h, scene, status)
fn(handle)
return
}
if _, ok := plugins.IndexSceneMap[scene]; ok {
/*if _, ok := plugins.IndexSceneMap[scene]; ok {
p, ok := h["pagination"]
if ok {
pp, ok := p.(pagination.ParsePagination)
@ -39,5 +34,5 @@ func Hook(themeName string, code int, c *gin.Context, h gin.H, scene, status int
c.HTML(code, "twentyfifteen/posts/detail.gohtml", h)
return
}
logs.ErrPrintln(errors.New("what happening"), " how reached here", themeName, code, h, scene, status)
logs.ErrPrintln(errors.New("what happening"), " how reached here", themeName, code, h, scene, status)*/
}

View File

@ -8,6 +8,7 @@ import (
"github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins"
"github.com/fthvgb1/wp-go/internal/theme/common"
"github.com/fthvgb1/wp-go/plugin/pagination"
"github.com/gin-gonic/gin"
"strings"
@ -26,53 +27,52 @@ var paginate = func() plugins.PageEle {
}()
type handle struct {
c *gin.Context
ginH gin.H
scene int
status int
stats int
common.Handle
templ string
}
func Hook(status int, c *gin.Context, ginH gin.H, scene, stats int) {
func Hook(h2 common.Handle) {
h := handle{
c: c,
ginH: ginH,
scene: scene,
status: status,
stats: stats,
Handle: h2,
templ: "twentyseventeen/posts/index.gohtml",
}
ginH["HeaderImage"] = h.getHeaderImage(c)
if stats == plugins.Empty404 {
c.HTML(status, h.templ, ginH)
h.GinH["HeaderImage"] = h.getHeaderImage(h.C)
if h.Stats == plugins.Empty404 {
h.C.HTML(h.Code, h.templ, h.GinH)
return
}
if scene == plugins.Detail {
if h.Scene == plugins.Detail {
h.detail()
return
}
h.index()
}
var plugin = []common.Plugin[models.Posts]{
common.PasswordProject, common.Digest,
}
func (h handle) index() {
posts := h.ginH["posts"].([]models.Posts)
p, ok := h.ginH["pagination"]
if h.Stats != plugins.Empty404 {
posts := h.GinH["posts"].([]models.Posts)
posts = slice.Map(posts, common.PluginFn(plugin, h.Handle, common.Default[models.Posts]))
p, ok := h.GinH["pagination"]
if ok {
pp, ok := p.(pagination.ParsePagination)
if ok {
h.ginH["pagination"] = pagination.Paginate(paginate, pp)
h.GinH["pagination"] = pagination.Paginate(paginate, pp)
}
}
h.ginH["bodyClass"] = h.bodyClass()
h.ginH["posts"] = h.postThumbnail(posts, h.scene)
h.c.HTML(h.status, h.templ, h.ginH)
h.GinH["posts"] = h.postThumbnail(posts, h.Scene)
}
h.GinH["bodyClass"] = h.bodyClass()
h.C.HTML(h.Code, h.templ, h.GinH)
}
func (h handle) detail() {
post := h.ginH["post"].(models.Posts)
h.ginH["bodyClass"] = h.bodyClass()
post := h.GinH["post"].(models.Posts)
h.GinH["bodyClass"] = h.bodyClass()
//host, _ := wpconfig.Options.Load("siteurl")
host := ""
img := plugins.Thumbnail(post.Thumbnail.OriginAttachmentData, "thumbnail", host, "thumbnail", "post-thumbnail")
@ -81,12 +81,12 @@ func (h handle) detail() {
img.Sizes = "100vw"
img.Srcset = fmt.Sprintf("%s %dw, %s", img.Path, img.Width, img.Srcset)
post.Thumbnail = img
h.ginH["post"] = post
comments := h.ginH["comments"].([]models.Comments)
dep := h.ginH["maxDep"].(int)
h.ginH["comments"] = plugins.FormatComments(h.c, comment{}, comments, dep)
h.GinH["post"] = post
comments := h.GinH["comments"].([]models.Comments)
dep := h.GinH["maxDep"].(int)
h.GinH["comments"] = plugins.FormatComments(h.C, comment{}, comments, dep)
h.templ = "twentyseventeen/posts/detail.gohtml"
h.c.HTML(h.status, h.templ, h.ginH)
h.C.HTML(h.Code, h.templ, h.GinH)
}
type comment struct {
@ -137,18 +137,18 @@ func (h handle) getHeaderImage(c *gin.Context) (r models.PostThumbnail) {
func (h handle) bodyClass() string {
s := ""
switch h.scene {
switch h.Scene {
case plugins.Search:
s = "search-no-results"
if len(h.ginH["posts"].([]models.Posts)) > 0 {
if len(h.GinH["posts"].([]models.Posts)) > 0 {
s = "search-results"
}
case plugins.Category, plugins.Tag:
cat := h.c.Param("category")
cat := h.C.Param("category")
if cat == "" {
cat = h.c.Param("tag")
cat = h.C.Param("tag")
}
_, cate := slice.SearchFirst(cache.CategoriesTags(h.c, h.scene), func(my models.TermsMy) bool {
_, cate := slice.SearchFirst(cache.CategoriesTags(h.C, h.Scene), func(my models.TermsMy) bool {
return my.Name == cat
})
if cate.Slug[0] != '%' {
@ -156,9 +156,9 @@ func (h handle) bodyClass() string {
}
s = fmt.Sprintf("category-%d %v", cate.Terms.TermId, s)
case plugins.Detail:
s = fmt.Sprintf("postid-%d", h.ginH["post"].(models.Posts).Id)
s = fmt.Sprintf("postid-%d", h.GinH["post"].(models.Posts).Id)
}
return str.Join(class[h.scene], s)
return str.Join(class[h.Scene], s)
}
var class = map[int]string{