282 lines
6 KiB
Go
282 lines
6 KiB
Go
package action
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/yaoapp/gou"
|
|
"github.com/yaoapp/gou/session"
|
|
"github.com/yaoapp/kun/any"
|
|
"github.com/yaoapp/kun/exception"
|
|
"github.com/yaoapp/kun/log"
|
|
"github.com/yaoapp/yao/widgets/hook"
|
|
)
|
|
|
|
// Bind the process name
|
|
func (p *Process) Bind(processName string) {
|
|
p.ProcessBind = processName
|
|
}
|
|
|
|
// SetName set the process name
|
|
func (p *Process) SetName(name string) {
|
|
p.Name = name
|
|
}
|
|
|
|
// SetHandler set the handler
|
|
func (p *Process) SetHandler(handler Handler) *Process {
|
|
p.Handler = handler
|
|
return p
|
|
}
|
|
|
|
// Merge a process
|
|
func (p *Process) Merge(newProcess *Process) *Process {
|
|
|
|
if newProcess == nil {
|
|
return p
|
|
}
|
|
|
|
if newProcess.Name != "" {
|
|
p.Name = newProcess.Name
|
|
}
|
|
|
|
if p.Process == "" {
|
|
p.Process = newProcess.Process
|
|
}
|
|
|
|
if p.ProcessBind == "" {
|
|
p.ProcessBind = newProcess.ProcessBind
|
|
}
|
|
|
|
if p.Guard == "" {
|
|
p.Guard = newProcess.Guard
|
|
}
|
|
|
|
p.DefaultMerge(newProcess.Default)
|
|
return p
|
|
}
|
|
|
|
// DefaultMerge merge the default value.
|
|
// option[0] the default is false, if true overwrite by the default value;
|
|
// option[1] the default is true, if true deep merge map and slice;
|
|
func (p *Process) DefaultMerge(defaults []interface{}, option ...bool) {
|
|
|
|
overwrite := false
|
|
if len(option) > 0 && option[0] {
|
|
overwrite = true
|
|
}
|
|
|
|
deep := true
|
|
if len(option) > 1 && !option[1] {
|
|
deep = false
|
|
}
|
|
|
|
if defaults == nil {
|
|
return
|
|
}
|
|
|
|
if p.Default == nil {
|
|
p.Default = []interface{}{}
|
|
}
|
|
|
|
length := len(p.Default)
|
|
for idx, value := range defaults {
|
|
if idx >= length {
|
|
p.Default = append(p.Default, value)
|
|
continue
|
|
}
|
|
if value != nil {
|
|
p.Default[idx] = p.mergeDefaultValue("", p.Default[idx], value, overwrite, deep)
|
|
}
|
|
}
|
|
}
|
|
|
|
// WithBefore bind before hook
|
|
func (p *Process) WithBefore(before *hook.Before) *Process {
|
|
p.Before = before
|
|
return p
|
|
}
|
|
|
|
// WithAfter bind after hook
|
|
func (p *Process) WithAfter(after *hook.After) *Process {
|
|
p.After = after
|
|
return p
|
|
}
|
|
|
|
// Args get the process args
|
|
func (p *Process) Args(process *gou.Process) []interface{} {
|
|
process.ValidateArgNums(1)
|
|
args := []interface{}{}
|
|
args = append(args, p.Default...)
|
|
nums := len(process.Args[1:])
|
|
if nums > len(args) {
|
|
nums = len(args)
|
|
}
|
|
|
|
for i := 0; i < nums; i++ {
|
|
input := process.Args[i+1]
|
|
defaultValue := args[i]
|
|
args[i] = p.mergeDefaultValue(process.Sid, input, defaultValue, false, true)
|
|
// fmt.Printf("-Args--\n%#v\n===\n%#v\n-END Args--\n\n", input, args[i])
|
|
}
|
|
return args
|
|
}
|
|
|
|
// Exec exec the process
|
|
func (p *Process) Exec(process *gou.Process) (interface{}, error) {
|
|
if p.Handler == nil {
|
|
return nil, fmt.Errorf("%s handler does not set", p.Name)
|
|
}
|
|
return p.Handler(p, process)
|
|
}
|
|
|
|
// MustExec exec the process
|
|
func (p *Process) MustExec(process *gou.Process) interface{} {
|
|
res, err := p.Exec(process)
|
|
if err != nil {
|
|
exception.New(err.Error(), 500).Throw()
|
|
}
|
|
return res
|
|
}
|
|
|
|
// deepMergeDefault deep merge args
|
|
func (p *Process) mergeDefaultValue(sid string, value interface{}, defaultValue interface{}, overwrite bool, deep bool) interface{} {
|
|
|
|
switch defaultValue.(type) {
|
|
|
|
case map[string]interface{}:
|
|
return p.mergeDefaultMap(sid, value, defaultValue.(map[string]interface{}), overwrite, deep)
|
|
|
|
case []interface{}:
|
|
return p.mergeDefaultSlice(sid, value, defaultValue.([]interface{}), overwrite, deep)
|
|
|
|
case string:
|
|
return p.mergeDefaultString(sid, value, defaultValue.(string), overwrite)
|
|
}
|
|
|
|
if value == nil || overwrite {
|
|
return defaultValue
|
|
}
|
|
|
|
if vstr, ok := value.(string); ok && vstr == "" {
|
|
return defaultValue
|
|
} else if vint, ok := value.(int); ok && vint == 0 {
|
|
return defaultValue
|
|
}
|
|
|
|
return value
|
|
}
|
|
|
|
func (p *Process) mergeDefaultMap(sid string, value interface{}, defaultValues map[string]interface{}, overwrite bool, deep bool) interface{} {
|
|
if value == nil {
|
|
value = map[string]interface{}{}
|
|
// return defaultValues
|
|
}
|
|
|
|
vmap := map[string]interface{}(any.Of(value).Map().MapStrAny)
|
|
// fmt.Printf("-vmap--\n%#v\n-end vmap--\n\n", vmap)
|
|
|
|
for k, v := range defaultValues {
|
|
// fmt.Printf("-vmap k:v--\n%#v:%#v\n-end vmap k:v--\n\n", k, v)
|
|
|
|
if _, has := vmap[k]; !has || overwrite || deep {
|
|
if deep {
|
|
vmap[k] = p.mergeDefaultValue(sid, vmap[k], v, overwrite, deep)
|
|
continue
|
|
}
|
|
vmap[k] = v
|
|
}
|
|
}
|
|
|
|
// delete keys
|
|
if overwrite && !deep {
|
|
for k := range vmap {
|
|
if _, has := defaultValues[k]; !has {
|
|
delete(vmap, k)
|
|
}
|
|
}
|
|
}
|
|
|
|
return vmap
|
|
}
|
|
|
|
func (p *Process) mergeDefaultSlice(sid string, value interface{}, defaultValues []interface{}, overwrite bool, deep bool) interface{} {
|
|
if value == nil {
|
|
value = []interface{}{}
|
|
// return defaultValues
|
|
}
|
|
|
|
varr := any.Of(value).CArray()
|
|
// fmt.Printf("-varr--\n%#v\n-end varr--\n\n", defaultValues)
|
|
|
|
length := len(varr)
|
|
for i, v := range defaultValues {
|
|
if i >= length {
|
|
if deep {
|
|
varr = append(varr, p.mergeDefaultValue(sid, nil, v, overwrite, deep))
|
|
// fmt.Printf("-varr-deep --\n%#v\n-end varr--\n\n", varr)
|
|
continue
|
|
}
|
|
|
|
varr = append(varr, v)
|
|
continue
|
|
}
|
|
|
|
if overwrite {
|
|
if deep {
|
|
varr[i] = p.mergeDefaultValue(sid, varr[i], v, overwrite, deep)
|
|
} else {
|
|
varr[i] = v
|
|
}
|
|
}
|
|
}
|
|
|
|
// delete keys
|
|
if overwrite && !deep && length > len(defaultValues) {
|
|
varr = varr[:len(defaultValues)]
|
|
}
|
|
|
|
return varr
|
|
}
|
|
|
|
func (p *Process) mergeDefaultString(sid string, value interface{}, defaultValue string, overwrite bool) interface{} {
|
|
|
|
if value == nil || overwrite {
|
|
value = defaultValue
|
|
}
|
|
|
|
if valueStr, ok := value.(string); ok && sid != "" {
|
|
|
|
if valueStr == "" {
|
|
return defaultValue
|
|
}
|
|
|
|
// Session $.user.id $.user_id
|
|
v := strings.TrimSpace(valueStr)
|
|
if strings.HasPrefix(v, "$.") {
|
|
name := strings.TrimLeft(v, "$.")
|
|
namer := strings.Split(name, ".")
|
|
|
|
val, err := session.Global().ID(sid).Get(namer[0])
|
|
|
|
if err != nil {
|
|
exception.New("Get %s %s", 500, v, err.Error()).Throw()
|
|
return nil
|
|
}
|
|
|
|
// $.user_id
|
|
if len(namer) == 1 {
|
|
log.Trace("[Session] %s %v", v, val)
|
|
return val
|
|
}
|
|
|
|
// $.user.id
|
|
mapping := any.Of(val).MapStr().Dot()
|
|
val = mapping.Get(strings.Join(namer[1:], "."))
|
|
log.Trace("[Session] %s %v", v, val)
|
|
return val
|
|
}
|
|
|
|
}
|
|
|
|
return value
|
|
}
|