-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathcallback.go
122 lines (105 loc) · 3.19 KB
/
callback.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package media_library
import (
"encoding/json"
"errors"
"mime/multipart"
"reflect"
"github.com/jinzhu/gorm"
"github.com/qor/serializable_meta"
)
func cropField(field *gorm.Field, scope *gorm.Scope) (cropped bool) {
if field.Field.CanAddr() {
// TODO Handle scanner
if media, ok := field.Field.Addr().Interface().(Media); ok && !media.Cropped() {
option := parseTagOption(field.Tag.Get("media_library"))
if media.GetFileHeader() != nil || media.NeedCrop() {
var file multipart.File
var err error
if fileHeader := media.GetFileHeader(); fileHeader != nil {
file, err = media.GetFileHeader().Open()
} else {
file, err = media.Retrieve(media.URL("original"))
}
if err != nil {
scope.Err(err)
return false
}
media.Cropped(true)
if url := media.GetURL(option, scope, field, media); url == "" {
scope.Err(errors.New("invalid URL"))
} else {
result, _ := json.Marshal(map[string]string{"Url": url})
media.Scan(string(result))
}
if file != nil {
defer file.Close()
var handled = false
for _, handler := range mediaHandlers {
if handler.CouldHandle(media) {
file.Seek(0, 0)
if scope.Err(handler.Handle(media, file, option)) == nil {
handled = true
}
}
}
// Save File
if !handled {
scope.Err(media.Store(media.URL(), option, file))
}
}
return true
}
}
}
return false
}
func saveAndCropImage(isCreate bool) func(scope *gorm.Scope) {
return func(scope *gorm.Scope) {
if !scope.HasError() {
var updateColumns = map[string]interface{}{}
// Handle SerializableMeta
if value, ok := scope.Value.(serializable_meta.SerializableMetaInterface); ok {
var (
isCropped bool
handleNestedCrop func(record interface{})
)
handleNestedCrop = func(record interface{}) {
newScope := scope.New(record)
for _, field := range newScope.Fields() {
if cropField(field, scope) {
isCropped = true
continue
}
if reflect.Indirect(field.Field).Kind() == reflect.Struct {
handleNestedCrop(field.Field.Addr().Interface())
}
if reflect.Indirect(field.Field).Kind() == reflect.Slice {
for i := 0; i < reflect.Indirect(field.Field).Len(); i++ {
handleNestedCrop(reflect.Indirect(field.Field).Index(i).Addr().Interface())
}
}
}
}
record := value.GetSerializableArgument(value)
handleNestedCrop(record)
if isCreate && isCropped {
updateColumns["value"], _ = json.Marshal(record)
}
}
// Handle Normal Field
for _, field := range scope.Fields() {
if cropField(field, scope) && isCreate {
updateColumns[field.DBName] = field.Field.Interface()
}
}
if !scope.HasError() && len(updateColumns) != 0 {
scope.Err(scope.NewDB().Model(scope.Value).UpdateColumns(updateColumns).Error)
}
}
}
}
// RegisterCallbacks register callback into GORM DB
func RegisterCallbacks(db *gorm.DB) {
db.Callback().Update().Before("gorm:before_update").Register("media_library:save_and_crop", saveAndCropImage(false))
db.Callback().Create().After("gorm:after_create").Register("media_library:save_and_crop", saveAndCropImage(true))
}