2014-05-07 13:06:24 +08:00
|
|
|
package binder
|
|
|
|
|
|
|
|
import (
|
2015-11-13 17:58:41 +08:00
|
|
|
"github.com/leanote/leanote/app/info"
|
|
|
|
"github.com/revel/revel"
|
|
|
|
// "github.com/leanote/leanote/app/controllers/api"
|
2014-05-07 13:06:24 +08:00
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// leanote binder struct
|
|
|
|
// rewrite revel struct binder
|
2015-11-13 17:58:41 +08:00
|
|
|
// not need the struct name as prefix,
|
2014-05-07 13:06:24 +08:00
|
|
|
// eg:
|
|
|
|
// type Note struct {Name}
|
|
|
|
// func (c Controller) List(note Note) revel.Result {}
|
|
|
|
// in revel you must pass the note.Name as key, now you just pass Name
|
|
|
|
|
|
|
|
// for test
|
|
|
|
// map[string][string]
|
|
|
|
var MSSBinder = revel.Binder{
|
|
|
|
Bind: func(params *revel.Params, name string, typ reflect.Type) reflect.Value {
|
|
|
|
var (
|
|
|
|
result = reflect.MakeMap(typ)
|
|
|
|
keyType = typ.Key()
|
|
|
|
valueType = typ.Elem()
|
|
|
|
)
|
|
|
|
for paramName, values := range params.Values {
|
|
|
|
key := paramName // [len(name)+1 : len(paramName)-1]
|
|
|
|
// 每一个值 values[0]
|
|
|
|
result.SetMapIndex(revel.BindValue(key, keyType), revel.BindValue(values[0], valueType))
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
},
|
2015-11-13 17:58:41 +08:00
|
|
|
|
2014-05-07 13:06:24 +08:00
|
|
|
Unbind: func(output map[string]string, name string, val interface{}) {
|
|
|
|
mapValue := reflect.ValueOf(val)
|
|
|
|
for _, key := range mapValue.MapKeys() {
|
|
|
|
revel.Unbind(output, fmt.Sprintf("%v", key.Interface()),
|
|
|
|
mapValue.MapIndex(key).Interface())
|
2015-11-13 17:58:41 +08:00
|
|
|
}
|
2014-05-07 13:06:24 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// struct需要., a.b = "life"
|
|
|
|
// a: contoller是形参名
|
|
|
|
// 修改, 默认就是a.b, 传b
|
|
|
|
func nextKey(key string) string {
|
|
|
|
fieldLen := strings.IndexAny(key, ".[")
|
|
|
|
if fieldLen == -1 {
|
|
|
|
return key
|
|
|
|
}
|
|
|
|
return key[:fieldLen]
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
2014-05-07 13:06:24 +08:00
|
|
|
var leanoteStructBinder = revel.Binder{
|
2015-03-31 14:27:26 +08:00
|
|
|
// name == "noteOrContent"
|
2014-05-07 13:06:24 +08:00
|
|
|
Bind: func(params *revel.Params, name string, typ reflect.Type) reflect.Value {
|
2015-03-31 14:27:26 +08:00
|
|
|
result := reflect.New(typ).Elem() // 创建一个该类型的, 然后其field从所有的param去取
|
2014-05-07 13:06:24 +08:00
|
|
|
fieldValues := make(map[string]reflect.Value)
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println(name)
|
2015-03-31 14:27:26 +08:00
|
|
|
// fmt.Println(typ) // api.NoteFiles
|
|
|
|
// name = files[0], files[1], noteContent
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println(params.Values)
|
2015-03-31 14:27:26 +08:00
|
|
|
/*
|
2015-11-28 21:26:29 +08:00
|
|
|
map[Title:[test1] METHOD:[POST] NotebookId:[54c4f51705fcd14031000002]
|
|
|
|
files[1][FileId]:[]
|
|
|
|
controller:[note]
|
|
|
|
files[1][LocalFileId]:[54c7ae27d98d0329dd000000] files[1][HasBody]:[true] files[0][FileId]:[] files[0][LocalFileId]:[54c7ae855e94ea2dba000000] action:[addNote] Content:[<p>lifedddddd</p><p><img src="app://leanote/data/54bdc65599c37b0da9000002/images/1422368307147_2.png" alt="" data-mce-src="app://leanote/data/54bdc65599c37b0da9000002/images/1422368307147_2.png" style="display: block; margin-left: auto; margin-right: auto;"></p><p><img src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae27d98d0329dd000000" alt="" data-mce-src="http://127.0.0.1:8008/api/file/getImg?fileId=54c7ae27d98d0329dd000000"></p><p><br></p><p><img src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae855e94ea2dba000000" alt="" data-mce-src="http://127.0.0.1:8008/api/file/getImage?fileId=54c7ae855e94ea2dba000000" style="display: block; margin-left: auto; margin-right: auto;"></p><p><br></p><p><br></p>] IsBlog:[false] token:[user1]
|
|
|
|
files[0][HasBody]:[true]]
|
2015-03-31 14:27:26 +08:00
|
|
|
*/
|
|
|
|
nameIsSlice := strings.Contains(name, "[")
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println(params.Values["files[1]"])
|
|
|
|
// fmt.Println(params.Values["Title"])
|
|
|
|
for key, _ := range params.Values { // Title, Content, Files
|
2014-05-07 13:06:24 +08:00
|
|
|
// 这里, 如果没有点, 默认就是a.
|
|
|
|
// life
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println("key:" + key); // files[0][LocalFileId]
|
|
|
|
// fmt.Println("name:" + name); // files[0][LocalFileId]
|
2014-05-07 13:06:24 +08:00
|
|
|
var suffix string
|
|
|
|
var noPrefix = false
|
2015-03-31 14:27:26 +08:00
|
|
|
if nameIsSlice && strings.HasPrefix(key, name) {
|
2015-11-13 17:58:41 +08:00
|
|
|
suffix = key[len(name)+1 : len(key)-1] // files[0][LocalFileId] 去掉 => LocalFileId
|
|
|
|
} else if !strings.HasPrefix(key, name+".") {
|
2014-05-07 13:06:24 +08:00
|
|
|
noPrefix = true
|
|
|
|
suffix = key
|
2015-11-13 17:58:41 +08:00
|
|
|
// continue
|
2014-05-07 13:06:24 +08:00
|
|
|
} else {
|
|
|
|
// Get the name of the struct property.
|
|
|
|
// Strip off the prefix. e.g. foo.bar.baz => bar.baz
|
|
|
|
suffix = key[len(name)+1:]
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println(suffix);
|
|
|
|
|
2014-05-07 13:06:24 +08:00
|
|
|
fieldName := nextKey(suffix) // e.g. bar => "bar", bar.baz => "bar", bar[0] => "bar"
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println(fieldName);
|
2014-05-07 13:06:24 +08:00
|
|
|
fieldLen := len(fieldName)
|
2015-11-13 17:58:41 +08:00
|
|
|
|
2014-05-07 13:06:24 +08:00
|
|
|
if _, ok := fieldValues[fieldName]; !ok {
|
|
|
|
// Time to bind this field. Get it and make sure we can set it.
|
2015-03-31 14:27:26 +08:00
|
|
|
fieldName = strings.Title(fieldName) // 传过来title, 但struct是Title
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println("xx: " + fieldName)
|
2014-05-07 13:06:24 +08:00
|
|
|
fieldValue := result.FieldByName(fieldName)
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println(fieldValue)
|
2014-05-07 13:06:24 +08:00
|
|
|
if !fieldValue.IsValid() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !fieldValue.CanSet() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
var boundVal reflect.Value
|
|
|
|
// 没有name前缀
|
2015-11-13 17:58:41 +08:00
|
|
|
if noPrefix {
|
2015-03-31 14:27:26 +08:00
|
|
|
// life
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println("<<")
|
|
|
|
// fmt.Println(strings.Title(key[:fieldLen]));
|
2014-05-07 13:06:24 +08:00
|
|
|
boundVal = revel.Bind(params, key[:fieldLen], fieldValue.Type())
|
|
|
|
} else {
|
2015-11-13 17:58:41 +08:00
|
|
|
// fmt.Println("final")
|
|
|
|
// fmt.Println(key[:len(name)+1+fieldLen]) // files[0][HasBody
|
2015-03-31 14:27:26 +08:00
|
|
|
if nameIsSlice {
|
|
|
|
fieldLen += 1
|
|
|
|
}
|
2014-05-07 13:06:24 +08:00
|
|
|
boundVal = revel.Bind(params, key[:len(name)+1+fieldLen], fieldValue.Type())
|
|
|
|
}
|
|
|
|
fieldValue.Set(boundVal)
|
|
|
|
fieldValues[fieldName] = boundVal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
},
|
|
|
|
Unbind: func(output map[string]string, name string, iface interface{}) {
|
|
|
|
val := reflect.ValueOf(iface)
|
|
|
|
typ := val.Type()
|
|
|
|
for i := 0; i < val.NumField(); i++ {
|
|
|
|
structField := typ.Field(i)
|
|
|
|
fieldValue := val.Field(i)
|
|
|
|
// PkgPath is specified to be empty exactly for exported fields.
|
|
|
|
if structField.PkgPath == "" {
|
|
|
|
revel.Unbind(output, fmt.Sprintf("%s.%s", name, structField.Name), fieldValue.Interface())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
revel.TypeBinders[reflect.TypeOf(info.UserBlogBase{})] = leanoteStructBinder
|
|
|
|
revel.TypeBinders[reflect.TypeOf(info.UserBlogComment{})] = leanoteStructBinder
|
|
|
|
revel.TypeBinders[reflect.TypeOf(info.UserBlogStyle{})] = leanoteStructBinder
|
|
|
|
revel.TypeBinders[reflect.TypeOf(info.Notebook{})] = leanoteStructBinder
|
2015-03-31 14:27:26 +08:00
|
|
|
revel.TypeBinders[reflect.TypeOf(info.UserAccount{})] = leanoteStructBinder
|
2015-11-28 21:26:29 +08:00
|
|
|
revel.TypeBinders[reflect.TypeOf(info.NoteOrContent{})] = leanoteStructBinder
|
2015-03-31 14:27:26 +08:00
|
|
|
revel.TypeBinders[reflect.TypeOf(info.ApiNote{})] = leanoteStructBinder
|
|
|
|
revel.TypeBinders[reflect.TypeOf(info.NoteFile{})] = leanoteStructBinder
|
2015-11-13 17:58:41 +08:00
|
|
|
}
|