mirror of
https://github.com/kataras/iris.git
synced 2025-12-19 10:57:05 +00:00
Update to 8.3.0 | MVC Models and Bindings and fix of #723 , read HISTORY.md
Former-commit-id: d8f66d8d370c583a288333df2a14c6ee2dc56466
This commit is contained in:
103
mvc/activator/persistence_data_control.go
Normal file
103
mvc/activator/persistence_data_control.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package activator
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
type field struct {
|
||||
Name string // by-defaultis the field's name but if `name: "other"` then it's overridden.
|
||||
Index int
|
||||
Type reflect.Type
|
||||
Value reflect.Value
|
||||
|
||||
embedded *field
|
||||
}
|
||||
|
||||
func (ff field) sendTo(elem reflect.Value) {
|
||||
if embedded := ff.embedded; embedded != nil {
|
||||
if ff.Index >= 0 {
|
||||
embedded.sendTo(elem.Field(ff.Index))
|
||||
}
|
||||
return
|
||||
}
|
||||
elemField := elem.Field(ff.Index)
|
||||
if elemField.Kind() == reflect.Ptr && !elemField.IsNil() {
|
||||
return
|
||||
}
|
||||
|
||||
elemField.Set(ff.Value)
|
||||
}
|
||||
|
||||
func lookupFields(t *TController, validator func(reflect.StructField) bool) (fields []field) {
|
||||
elem := t.Type.Elem()
|
||||
|
||||
for i, n := 0, elem.NumField(); i < n; i++ {
|
||||
elemField := elem.Field(i)
|
||||
valF := t.Value.Field(i)
|
||||
|
||||
// catch persistence data by tags, i.e:
|
||||
// MyData string `iris:"persistence"`
|
||||
if validator(elemField) {
|
||||
name := elemField.Name
|
||||
if nameTag, ok := elemField.Tag.Lookup("name"); ok {
|
||||
name = nameTag
|
||||
}
|
||||
|
||||
f := field{
|
||||
Name: name,
|
||||
Index: i,
|
||||
Type: elemField.Type,
|
||||
}
|
||||
|
||||
if valF.IsValid() || (valF.Kind() == reflect.Ptr && !valF.IsNil()) {
|
||||
val := reflect.ValueOf(valF.Interface())
|
||||
if val.IsValid() || (val.Kind() == reflect.Ptr && !val.IsNil()) {
|
||||
f.Value = val
|
||||
}
|
||||
}
|
||||
|
||||
fields = append(fields, f)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type persistenceDataControl struct {
|
||||
fields []field
|
||||
}
|
||||
|
||||
func (d *persistenceDataControl) Load(t *TController) error {
|
||||
fields := lookupFields(t, func(f reflect.StructField) bool {
|
||||
if tag, ok := f.Tag.Lookup("iris"); ok {
|
||||
if tag == "persistence" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if len(fields) == 0 {
|
||||
// first is the `Controller` so we need to
|
||||
// check the second and after that.
|
||||
return ErrControlSkip
|
||||
}
|
||||
|
||||
d.fields = fields
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *persistenceDataControl) Handle(ctx context.Context, c reflect.Value, methodFunc func()) {
|
||||
elem := c.Elem() // controller should always be a pointer at this state
|
||||
for _, f := range d.fields {
|
||||
f.sendTo(elem)
|
||||
}
|
||||
}
|
||||
|
||||
// PersistenceDataControl loads and re-stores
|
||||
// the persistence data by scanning the original
|
||||
// `TController.Value` instance of the user's controller.
|
||||
func PersistenceDataControl() TControl {
|
||||
return &persistenceDataControl{}
|
||||
}
|
||||
Reference in New Issue
Block a user