宇宙究极无知hook handle

This commit is contained in:
xing 2023-04-22 01:12:39 +08:00
parent 023212ba7b
commit 72bad0fa36
5 changed files with 159 additions and 160 deletions

View File

@ -16,6 +16,9 @@ const (
AllStats AllStats
AllScene AllScene
PipData
PipRender
Defaults = "default" Defaults = "default"
HeadScript = "headScript" HeadScript = "headScript"

View File

@ -41,7 +41,10 @@ func Init(fs embed.FS) {
} }
} }
var pipe = wp.HandlePipe(wp.ExecuteHandleFn, widget.MiddleWare(ready, wp.DataHandle)...) var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready,
wp.PipeHandle(constraints.PipData, wp.PipeKey, wp.PipeDataHandle),
wp.PipeHandle(constraints.PipRender, wp.PipeKey, wp.PipeRender),
)...)
func Hook(h *wp.Handle) { func Hook(h *wp.Handle) {
pipe(h) pipe(h)
@ -64,14 +67,14 @@ func configs(h *wp.Handle) {
h.CommonComponents() h.CommonComponents()
h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...)) h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...))
components.WidgetArea(h) components.WidgetArea(h)
h.PushRender(constraints.AllStats, wp.NewHandleFn(customHeader, 10)) h.PushRender(constraints.AllStats, wp.NewHandleFn(customHeader, 10, "customHeader"))
h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50)) h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 50, "wp.IndexRender"))
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50)) h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50, "wp.DetailRender"))
h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60)) h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60, "postThumb"))
h.PushDataHandler(constraints.Detail, wp.NewHandleFn(wp.Details, 100)) h.PushDataHandler(constraints.Detail, wp.NewHandleFn(wp.Details, 100, "wp.Details"))
h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.Indexs, 100)) h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.Indexs, 100, "wp.Indexs"))
h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 80)) h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 80, "wp.PreCodeAndStats"))
h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreTemplate, 70)) h.PushRender(constraints.AllScene, wp.NewHandleFn(wp.PreTemplate, 70, "wp.PreTemplate"))
} }
func postThumb(h *wp.Handle) { func postThumb(h *wp.Handle) {

View File

@ -42,7 +42,10 @@ var paginate = func() plugins.PageEle {
return p return p
}() }()
var pipe = wp.HandlePipe(wp.ExecuteHandleFn, widget.MiddleWare(ready, wp.DataHandle)...) var pipe = wp.HandlePipe(wp.NothingToDo, widget.MiddleWare(ready,
wp.PipeHandle(constraints.PipData, wp.PipeKey, wp.PipeDataHandle),
wp.PipeHandle(constraints.PipRender, wp.PipeKey, wp.PipeRender),
)...)
func Hook(h *wp.Handle) { func Hook(h *wp.Handle) {
pipe(h) pipe(h)
@ -55,23 +58,24 @@ func configs(h *wp.Handle) {
h.PushCacheGroupHeadScript("colorScheme-customHeader", 10, colorScheme, customHeader) h.PushCacheGroupHeadScript("colorScheme-customHeader", 10, colorScheme, customHeader)
components.WidgetArea(h) components.WidgetArea(h)
pushScripts(h) pushScripts(h)
h.PushRender(constraints.AllStats, wp.NewHandleFn(func(h *wp.Handle) { h.PushRender(constraints.AllStats, wp.NewHandleFn(headerImage, 10, "headerImage"))
h.SetData("HeaderImage", getHeaderImage(h))
}, 10))
h.SetComponentsArgs(widgets.Widget, map[string]string{ h.SetComponentsArgs(widgets.Widget, map[string]string{
"{$before_widget}": `<section id="%s" class="%s">`, "{$before_widget}": `<section id="%s" class="%s">`,
"{$after_widget}": `</section>`, "{$after_widget}": `</section>`,
}) })
h.PushGroupRender(constraints.AllStats, 90, wp.PreTemplate, errorsHandle) h.PushRender(constraints.AllStats,
wp.NewHandleFn(wp.PreTemplate, 70, "wp.PreTemplate"),
wp.NewHandleFn(errorsHandle, 80, "errorsHandle"),
)
h.CommonComponents() h.CommonComponents()
h.Index.SetPageEle(paginate) h.Index.SetPageEle(paginate)
h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(postThumbnail), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...)) h.Index.SetListPlugin(wp.PostsPlugins(wp.PostPlugin(postThumbnail), wp.GetListPostPlugins(conf.ListPagePlugins, wp.ListPostPlugins())...))
wp.SetComponentsArgsForMap(h, widgets.Search, "{$form}", searchForm) wp.SetComponentsArgsForMap(h, widgets.Search, "{$form}", searchForm)
h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 10)) h.PushRender(constraints.AllStats, wp.NewHandleFn(wp.IndexRender, 10, "wp.IndexRender"))
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 10)) h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 10, "wp.DetailRender"))
h.PushDataHandler(constraints.Detail, wp.NewHandleFn(detail, 100)) h.PushDataHandler(constraints.Detail, wp.NewHandleFn(detail, 100, "detail"))
h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(index, 100)) h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(index, 100, "index"))
h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 90)) h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 90, "wp.PreCodeAndStats"))
} }
func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) { func ready(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
wp.InitThemeArgAndConfig(configs, h) wp.InitThemeArgAndConfig(configs, h)
@ -156,6 +160,10 @@ func postThumbnail(h *wp.Handle, posts *models.Posts) {
var header = reload.Vars(models.PostThumbnail{}) var header = reload.Vars(models.PostThumbnail{})
func headerImage(h *wp.Handle) {
h.SetData("HeaderImage", getHeaderImage(h))
}
func getHeaderImage(h *wp.Handle) (r models.PostThumbnail) { func getHeaderImage(h *wp.Handle) (r models.PostThumbnail) {
img := header.Load() img := header.Load()
if img.Path != "" { if img.Path != "" {

105
internal/theme/wp/pipe.go Normal file
View File

@ -0,0 +1,105 @@
package wp
import (
"fmt"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/cmd/reload"
"github.com/fthvgb1/wp-go/internal/pkg/constraints"
)
type HandlePipeFn[T any] func(HandleFn[T], T)
// HandlePipe 方便把功能写在其它包里
func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f func(t T)) func(t T) {
return func(t T) {
next(f, t)
}
}, initial)
}
func (h *Handle) PushHandler(pipScene int, scene int, fns ...HandleCall) {
if _, ok := h.handlers[pipScene]; !ok {
h.handlers[pipScene] = make(map[int][]HandleCall)
}
h.handlers[pipScene][scene] = append(h.handlers[pipScene][scene], fns...)
}
func (h *Handle) PushRender(statsOrScene int, fns ...HandleCall) {
h.PushHandler(constraints.PipRender, statsOrScene, fns...)
}
func (h *Handle) PushDataHandler(scene int, fns ...HandleCall) {
h.PushHandler(constraints.PipData, scene, fns...)
}
func PipeHandle(pipeScene int, keyFn func(*Handle, int) string, fn func(*Handle, map[int][]HandleCall) []HandleCall) func(HandleFn[*Handle], *Handle) {
return func(next HandleFn[*Handle], h *Handle) {
handlers := reload.SafetyMapBy("pipHandlers", keyFn(h, pipeScene), h, func(h *Handle) []HandleCall {
conf := h.handleHook[pipeScene]
calls := fn(h, h.handlers[pipeScene])
calls = slice.FilterAndMap(calls, func(call HandleCall) (HandleCall, bool) {
ok := true
for _, hook := range conf {
call, ok = hook(call)
if !ok {
break
}
}
return call, ok
})
slice.Sort(calls, func(i, j HandleCall) bool {
return i.Order > j.Order
})
return calls
})
for _, handler := range handlers {
handler.Fn(h)
if h.abort {
break
}
}
if !h.stopPipe {
next(h)
}
}
}
func PipeKey(h *Handle, pipScene int) string {
return fmt.Sprintf("%d-%d-%d", pipScene, h.scene, h.scene)
}
func PipeDataHandle(h *Handle, dataHandlers map[int][]HandleCall) (handlers []HandleCall) {
handlers = append(handlers, dataHandlers[h.scene]...)
handlers = append(handlers, dataHandlers[constraints.AllScene]...)
return
}
func PipeRender(h *Handle, renders map[int][]HandleCall) (handlers []HandleCall) {
handlers = append(handlers, renders[h.Stats]...)
handlers = append(handlers, renders[h.scene]...)
handlers = append(handlers, renders[constraints.AllStats]...)
handlers = append(handlers, renders[constraints.AllScene]...)
return
}
// DeleteHandle 写插件的时候用
func (h *Handle) DeleteHandle(pipeScene int, name string) {
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) {
return call, name != call.Name
})
}
// ReplaceHandle 写插件的时候用
func (h *Handle) ReplaceHandle(pipeScene int, name string, fn HandleFn[*Handle]) {
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) {
if name == call.Name {
call.Fn = fn
}
return call, true
})
}
// HookHandle 写插件的时候用
func (h *Handle) HookHandle(pipeScene int, hook func(HandleCall) (HandleCall, bool)) {
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], hook)
}

View File

@ -1,7 +1,6 @@
package wp package wp
import ( import (
"fmt"
"github.com/fthvgb1/wp-go/helper/maps" "github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
@ -30,21 +29,13 @@ type Handle struct {
templ string templ string
components map[string][]Components[string] components map[string][]Components[string]
themeMods wpconfig.ThemeMods themeMods wpconfig.ThemeMods
renders map[int][]HandleCall handlers map[int]map[int][]HandleCall
dataHandler map[int][]HandleCall handleHook map[int][]func(HandleCall) (HandleCall, bool)
err error err error
abort bool abort bool
stopPipe bool
componentsArgs map[string]any componentsArgs map[string]any
componentFilterFn map[string][]func(*Handle, string, ...any) string componentFilterFn map[string][]func(*Handle, string, ...any) string
handleCall []HandleCall
}
func (h *Handle) HandleCall() []HandleCall {
return h.handleCall
}
func (h *Handle) SetHandleCall(handleCall []HandleCall) {
h.handleCall = handleCall
} }
type HandlePlugins map[string]HandleFn[*Handle] type HandlePlugins map[string]HandleFn[*Handle]
@ -59,21 +50,20 @@ type Components[T any] struct {
type HandleFn[T any] func(T) type HandleFn[T any] func(T)
type HandlePipeFn[T any] func(HandleFn[T], T)
type HandleCall struct { type HandleCall struct {
Fn HandleFn[*Handle] Fn HandleFn[*Handle]
Order int Order int
Name string
} }
func InitThemeArgAndConfig(fn func(*Handle), h *Handle) { func InitThemeArgAndConfig(fn func(*Handle), h *Handle) {
var inited = false var inited = false
hh := reload.GetAnyValBys("themeArgAndConfig", h, func(h *Handle) Handle { hh := reload.GetAnyValBys("themeArgAndConfig", h, func(h *Handle) Handle {
h.components = make(map[string][]Components[string]) h.components = make(map[string][]Components[string])
h.renders = make(map[int][]HandleCall)
h.dataHandler = make(map[int][]HandleCall)
h.componentsArgs = make(map[string]any) h.componentsArgs = make(map[string]any)
h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string) h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string)
h.handlers = make(map[int]map[int][]HandleCall)
h.handleHook = make(map[int][]func(HandleCall) (HandleCall, bool))
h.ginH = gin.H{} h.ginH = gin.H{}
fn(h) fn(h)
inited = true inited = true
@ -99,8 +89,8 @@ func InitThemeArgAndConfig(fn func(*Handle), h *Handle) {
h.Index.postsPlugin = hh.Index.postsPlugin h.Index.postsPlugin = hh.Index.postsPlugin
h.Index.pageEle = hh.Index.pageEle h.Index.pageEle = hh.Index.pageEle
h.Detail.CommentRender = hh.Detail.CommentRender h.Detail.CommentRender = hh.Detail.CommentRender
h.renders = hh.renders h.handlers = hh.handlers
h.dataHandler = hh.dataHandler h.handleHook = hh.handleHook
h.componentsArgs = hh.componentsArgs h.componentsArgs = hh.componentsArgs
h.componentFilterFn = hh.componentFilterFn h.componentFilterFn = hh.componentFilterFn
} }
@ -126,6 +116,9 @@ func (h *Handle) ComponentFilterFnHook(name, s string, args ...any) string {
func (h *Handle) Abort() { func (h *Handle) Abort() {
h.abort = true h.abort = true
} }
func (h *Handle) StopPipe() {
h.stopPipe = true
}
func (h *Handle) CommonThemeMods() wpconfig.ThemeMods { func (h *Handle) CommonThemeMods() wpconfig.ThemeMods {
return h.themeMods return h.themeMods
@ -230,47 +223,6 @@ func (h *Handle) NewCacheComponent(name string, order int, fn func(handle *Handl
return Components[string]{Fn: fn, CacheKey: name, Order: order} return Components[string]{Fn: fn, CacheKey: name, Order: order}
} }
func (h *Handle) PushRender(statsOrScene int, fns ...HandleCall) {
h.renders[statsOrScene] = append(h.renders[statsOrScene], fns...)
}
func (h *Handle) PushDataHandler(Scene int, fns ...HandleCall) {
h.dataHandler[Scene] = append(h.dataHandler[Scene], fns...)
}
func (h *Handle) PushGroupRender(statsOrScene, order int, fns ...HandleFn[*Handle]) {
var calls []HandleCall
for _, fn := range fns {
calls = append(calls, HandleCall{fn, order})
}
h.renders[statsOrScene] = append(h.renders[statsOrScene], calls...)
}
func (h *Handle) PushGroupDataHandler(scene, order int, fns ...HandleFn[*Handle]) {
var calls []HandleCall
for _, fn := range fns {
calls = append(calls, HandleCall{fn, order})
}
h.dataHandler[scene] = append(h.dataHandler[scene], calls...)
}
func DataHandle(next HandleFn[*Handle], h *Handle) {
handlers := reload.SafetyMapBy("dataHandle", h.scene, h, func(h *Handle) []HandleCall {
a := h.dataHandler[h.scene]
aa, ok := h.dataHandler[constraints.AllScene]
if ok {
a = append(a, aa...)
}
slice.Sort(a, func(i, j HandleCall) bool {
return i.Order > j.Order
})
return a
})
for _, handler := range handlers {
handler.Fn(h)
}
h.DetermineHandleFns()
next(h)
}
func (h *Handle) AddCacheComponent(name string, fn func(*Handle) string) { func (h *Handle) AddCacheComponent(name string, fn func(*Handle) string) {
h.components[name] = append(h.components[name], h.NewCacheComponent(name, 10, fn)) h.components[name] = append(h.components[name], h.NewCacheComponent(name, 10, fn))
} }
@ -311,31 +263,6 @@ func (h *Handle) GetPassword() {
} }
} }
func (h *Handle) ExecHandleFns() {
calls, ok := h.renders[h.Stats]
var fns []HandleCall
if ok {
fns = append(fns, calls...)
}
calls, ok = h.renders[h.scene]
if ok {
fns = append(fns, calls...)
}
calls, ok = h.renders[constraints.AllStats]
if ok {
fns = append(fns, calls...)
}
slice.Sort(fns, func(i, j HandleCall) bool {
return i.Order > j.Order
})
for _, fn := range fns {
fn.Fn(h)
if h.abort {
break
}
}
}
func PreTemplate(h *Handle) { func PreTemplate(h *Handle) {
if h.templ == "" { if h.templ == "" {
h.templ = str.Join(h.theme, "/posts/index.gohtml") h.templ = str.Join(h.theme, "/posts/index.gohtml")
@ -358,18 +285,16 @@ func PreCodeAndStats(h *Handle) {
} }
} }
func (h *Handle) Render() {
h.CommonComponents()
h.ExecHandleFns()
}
func (h *Handle) CommonComponents() { func (h *Handle) CommonComponents() {
h.AddCacheComponent("customLogo", CalCustomLogo) h.AddCacheComponent("customLogo", CalCustomLogo)
h.PushCacheGroupHeadScript("siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss) h.PushCacheGroupHeadScript("siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss)
h.PushGroupRender(constraints.AllStats, 10, CalComponents) h.PushRender(constraints.AllStats, NewHandleFn(CalComponents, 10, "wp.CalComponents"))
h.PushRender(constraints.AllStats, NewHandleFn(func(h *Handle) { h.PushRender(constraints.AllStats, NewHandleFn(RenderTemplate, 0, "wp.RenderTemplate"))
h.C.HTML(h.Code, h.templ, h.ginH) }
}, 0))
func RenderTemplate(h *Handle) {
h.C.HTML(h.Code, h.templ, h.ginH)
h.StopPipe()
} }
func (h *Handle) PushComponents(name string, components ...Components[string]) { func (h *Handle) PushComponents(name string, components ...Components[string]) {
@ -424,55 +349,10 @@ func CalComponents(h *Handle) {
} }
} }
func NewHandleFn(fn HandleFn[*Handle], order int) HandleCall { func NewHandleFn(fn HandleFn[*Handle], order int, name string) HandleCall {
return HandleCall{Fn: fn, Order: order} return HandleCall{Fn: fn, Order: order, Name: name}
} }
// HandlePipe 方便把功能写在其它包里 func NothingToDo(*Handle) {
func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f func(t T)) func(t T) {
return func(t T) {
next(f, t)
}
}, initial)
}
func DetermineHandleFn(h *Handle) []HandleCall {
calls, ok := h.renders[h.Stats]
var fns []HandleCall
if ok {
fns = append(fns, calls...)
}
calls, ok = h.renders[h.scene]
if ok {
fns = append(fns, calls...)
}
calls, ok = h.renders[constraints.AllStats]
if ok {
fns = append(fns, calls...)
}
calls, ok = h.renders[constraints.AllScene]
if ok {
fns = append(fns, calls...)
}
slice.Sort(fns, func(i, j HandleCall) bool {
return i.Order > j.Order
})
return fns
}
func (h *Handle) DetermineHandleFns() {
key := fmt.Sprintf("%d-%d", h.scene, h.Stats)
h.handleCall = reload.SafetyMapBy("handleCalls", key, h, func(h *Handle) []HandleCall {
return DetermineHandleFn(h)
})
}
func ExecuteHandleFn(h *Handle) {
for _, fn := range h.handleCall {
fn.Fn(h)
if h.abort {
break
}
}
} }