264 lines
7.8 KiB
Go
264 lines
7.8 KiB
Go
package wp
|
|
|
|
import (
|
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
|
"github.com/fthvgb1/wp-go/cache/reload"
|
|
"github.com/fthvgb1/wp-go/helper/maps"
|
|
"github.com/fthvgb1/wp-go/helper/slice"
|
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
"github.com/fthvgb1/wp-go/safety"
|
|
"strings"
|
|
)
|
|
|
|
var handleComponents = safety.NewMap[string, map[string][]Components[string]]()
|
|
var handleComponentHook = safety.NewMap[string, []func(Components[string]) (Components[string], bool)]()
|
|
|
|
var componentsArgs = safety.NewMap[string, any]()
|
|
var componentFilterFns = safety.NewMap[string, []func(*Handle, string, ...any) string]()
|
|
|
|
func (h *Handle) DeleteComponents(scene, name string) {
|
|
v, _ := handleComponentHook.Load(scene)
|
|
v = append(v, func(c Components[string]) (Components[string], bool) {
|
|
return c, c.Name != name
|
|
})
|
|
handleComponentHook.Store(scene, v)
|
|
}
|
|
func (h *Handle) ReplaceComponents(scene, name string, components Components[string]) {
|
|
v, _ := handleComponentHook.Load(scene)
|
|
v = append(v, func(c Components[string]) (Components[string], bool) {
|
|
if c.Name == name {
|
|
c = components
|
|
}
|
|
return c, true
|
|
})
|
|
handleComponentHook.Store(scene, v)
|
|
}
|
|
func (h *Handle) HookComponents(scene string, fn func(Components[string]) (Components[string], bool)) {
|
|
v, _ := handleComponentHook.Load(scene)
|
|
v = append(v, fn)
|
|
handleComponentHook.Store(scene, v)
|
|
}
|
|
|
|
var getComponentFn = reload.BuildMapFn[string]("scene-components", getComponent)
|
|
var hookComponentFn = reload.BuildMapFn[string]("calComponents", hookComponent)
|
|
|
|
type componentParam struct {
|
|
components []Components[string]
|
|
k string
|
|
}
|
|
|
|
func hookComponent(p componentParam) []Components[string] {
|
|
mut := reload.GetGlobeMutex()
|
|
mut.Lock()
|
|
allHooks := slice.FilterAndToMap(p.components, func(t Components[string], _ int) (string, []func(Components[string]) (Components[string], bool), bool) {
|
|
fn, ok := handleComponentHook.Load(p.k)
|
|
return p.k, fn, ok
|
|
})
|
|
mut.Unlock()
|
|
r := slice.FilterAndMap(p.components, func(component Components[string]) (Components[string], bool) {
|
|
hooks, ok := allHooks[p.k]
|
|
if !ok {
|
|
return component, true
|
|
}
|
|
for _, fn := range hooks {
|
|
hookedComponent, ok := fn(component)
|
|
if !ok { // DeleteComponents fn
|
|
return hookedComponent, false
|
|
}
|
|
component = hookedComponent // ReplaceComponents fn
|
|
}
|
|
return component, true
|
|
})
|
|
slice.SimpleSort(r, slice.DESC, func(t Components[string]) float64 {
|
|
return t.Order
|
|
})
|
|
return r
|
|
}
|
|
|
|
func getComponent(h *Handle) map[string][]Components[string] {
|
|
mut := reload.GetGlobeMutex()
|
|
mut.Lock()
|
|
sceneComponents, _ := handleComponents.Load(h.scene)
|
|
allSceneComponents, _ := handleComponents.Load(constraints.AllScene)
|
|
|
|
mut.Unlock()
|
|
return maps.MergeBy(func(k string, c1, c2 []Components[string]) ([]Components[string], bool) {
|
|
vv := append(c1, c2...)
|
|
return vv, vv != nil
|
|
}, nil, sceneComponents, allSceneComponents)
|
|
}
|
|
|
|
type cacheComponentParm[T any] struct {
|
|
Components[T]
|
|
h *Handle
|
|
}
|
|
|
|
var cacheComponentsFn = reload.BuildMapFn[string]("cacheComponents", cacheComponentFn)
|
|
|
|
func cacheComponentFn(a cacheComponentParm[string]) string {
|
|
return a.Fn(a.h)
|
|
}
|
|
|
|
func CalComponents(h *Handle) {
|
|
allComponents := getComponentFn(str.Join("allScene-", h.scene), h)
|
|
for k, components := range allComponents {
|
|
key := str.Join("calComponents-", h.scene, "-", k)
|
|
hookedComponents := hookComponentFn(key, componentParam{components, k})
|
|
var s = make([]string, 0, len(hookedComponents))
|
|
for _, component := range hookedComponents {
|
|
if component.Val != "" {
|
|
s = append(s, component.Val)
|
|
continue
|
|
}
|
|
if component.Fn != nil {
|
|
v := ""
|
|
if component.Cached {
|
|
v = cacheComponentsFn(component.Name, cacheComponentParm[string]{component, h})
|
|
} else {
|
|
v = component.Fn(h)
|
|
}
|
|
if v != "" {
|
|
s = append(s, v)
|
|
}
|
|
}
|
|
}
|
|
h.ginH[k] = strings.Join(s, "\n")
|
|
}
|
|
}
|
|
|
|
func (h *Handle) PushComponents(scene, componentType string, components ...Components[string]) {
|
|
c, ok := handleComponents.Load(scene)
|
|
if !ok {
|
|
c = make(map[string][]Components[string])
|
|
}
|
|
c[componentType] = append(c[componentType], components...)
|
|
handleComponents.Store(scene, c)
|
|
}
|
|
|
|
func (h *Handle) PushGroupComponentStr(scene, componentType, name string, order float64, strs ...string) {
|
|
var component = Components[string]{
|
|
Val: strings.Join(slice.FilterAndMap(strs, func(t string) (string, bool) {
|
|
t = strings.Trim(t, " \n\r\t\v\x00")
|
|
if t == "" {
|
|
return "", false
|
|
}
|
|
return t, true
|
|
}), "\n"),
|
|
Order: order,
|
|
Name: name,
|
|
}
|
|
h.PushComponents(scene, componentType, component)
|
|
}
|
|
|
|
func (h *Handle) PushCacheGroupHeadScript(scene, name string, order float64, fns ...func(*Handle) string) {
|
|
h.PushGroupCacheComponentFn(scene, constraints.HeadScript, name, order, fns...)
|
|
}
|
|
|
|
func (h *Handle) PushFooterScript(scene string, components ...Components[string]) {
|
|
h.PushComponents(scene, constraints.FooterScript, components...)
|
|
}
|
|
|
|
func (h *Handle) PushGroupFooterScript(scene, name string, order float64, strs ...string) {
|
|
h.PushGroupComponentStr(scene, constraints.FooterScript, name, order, strs...)
|
|
}
|
|
|
|
func (h *Handle) PushCacheGroupFooterScript(scene, name string, order float64, fns ...func(*Handle) string) {
|
|
h.PushGroupCacheComponentFn(scene, constraints.FooterScript, name, order, fns...)
|
|
}
|
|
func (h *Handle) PushGroupCacheComponentFn(scene, componentType, name string, order float64, fns ...func(*Handle) string) {
|
|
h.PushComponents(scene, componentType, NewComponent(name, "", true, order, func(h *Handle) string {
|
|
return strings.Join(slice.Map(fns, func(t func(*Handle) string) string {
|
|
return t(h)
|
|
}), "\n")
|
|
}))
|
|
}
|
|
|
|
func NewComponent(name, val string, cached bool, order float64, fn func(handle *Handle) string) Components[string] {
|
|
return Components[string]{Fn: fn, Name: name, Cached: cached, Order: order, Val: val}
|
|
}
|
|
|
|
func (h *Handle) AddCacheComponent(scene, componentType, name string, order float64, fn func(*Handle) string) {
|
|
h.PushComponents(scene, componentType, NewComponent(name, "", true, order, fn))
|
|
}
|
|
|
|
func (h *Handle) PushHeadScript(scene string, components ...Components[string]) {
|
|
h.PushComponents(scene, constraints.HeadScript, components...)
|
|
}
|
|
func (h *Handle) PushGroupHeadScript(scene, name string, order float64, str ...string) {
|
|
h.PushGroupComponentStr(scene, constraints.HeadScript, name, order, str...)
|
|
}
|
|
|
|
func GetComponentsArgs[T any](k string, defaults T) T {
|
|
v, ok := componentsArgs.Load(k)
|
|
if ok {
|
|
vv, ok := v.(T)
|
|
if ok {
|
|
return vv
|
|
}
|
|
}
|
|
return defaults
|
|
}
|
|
|
|
func PushComponentsArgsForSlice[T any](name string, v ...T) {
|
|
val, ok := componentsArgs.Load(name)
|
|
if !ok {
|
|
var vv []T
|
|
vv = append(vv, v...)
|
|
componentsArgs.Store(name, vv)
|
|
return
|
|
}
|
|
vv, ok := val.([]T)
|
|
if ok {
|
|
vv = append(vv, v...)
|
|
componentsArgs.Store(name, vv)
|
|
}
|
|
}
|
|
func SetComponentsArgsForMap[K comparable, V any](name string, key K, v V) {
|
|
val, ok := componentsArgs.Load(name)
|
|
if !ok {
|
|
vv := make(map[K]V)
|
|
vv[key] = v
|
|
componentsArgs.Store(name, vv)
|
|
return
|
|
}
|
|
vv, ok := val.(map[K]V)
|
|
if ok {
|
|
vv[key] = v
|
|
componentsArgs.Store(name, vv)
|
|
}
|
|
}
|
|
func MergeComponentsArgsForMap[K comparable, V any](name string, m map[K]V) {
|
|
val, ok := componentsArgs.Load(name)
|
|
if !ok {
|
|
componentsArgs.Store(name, m)
|
|
return
|
|
}
|
|
vv, ok := val.(map[K]V)
|
|
if ok {
|
|
componentsArgs.Store(name, maps.Merge(vv, m))
|
|
}
|
|
}
|
|
|
|
func SetComponentsArgs(key string, value any) {
|
|
componentsArgs.Store(key, value)
|
|
}
|
|
|
|
func (h *Handle) GetComponentFilterFn(name string) ([]func(*Handle, string, ...any) string, bool) {
|
|
return componentFilterFns.Load(name)
|
|
}
|
|
|
|
func (h *Handle) AddActionFilter(name string, fns ...func(*Handle, string, ...any) string) {
|
|
v, _ := componentFilterFns.Load(name)
|
|
v = append(v, fns...)
|
|
componentFilterFns.Store(name, v)
|
|
}
|
|
func (h *Handle) DoActionFilter(name, s string, args ...any) string {
|
|
calls, ok := componentFilterFns.Load(name)
|
|
if ok {
|
|
return slice.Reduce(calls, func(fn func(*Handle, string, ...any) string, r string) string {
|
|
return fn(h, r, args...)
|
|
}, s)
|
|
}
|
|
return s
|
|
}
|