forked from qor/media
-
Notifications
You must be signed in to change notification settings - Fork 0
/
callback.go
133 lines (115 loc) · 3.53 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
123
124
125
126
127
128
129
130
131
132
133
package media
import (
"encoding/json"
"errors"
"reflect"
"github.com/jinzhu/gorm"
"github.com/qor/serializable_meta"
)
var (
// set MediaLibraryURL to change the default url /system/{{class}}/{{primary_key}}/{{column}}.{{extension}}
MediaLibraryURL = ""
)
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 MediaLibraryURL != "" {
option.Set("url", MediaLibraryURL)
}
if media.GetFileHeader() != nil || media.NeedCrop() {
var mediaFile FileInterface
var err error
if fileHeader := media.GetFileHeader(); fileHeader != nil {
mediaFile, err = media.GetFileHeader().Open()
} else {
mediaFile, 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 mediaFile != nil {
defer mediaFile.Close()
var handled = false
for _, handler := range mediaHandlers {
if handler.CouldHandle(media) {
mediaFile.Seek(0, 0)
if scope.Err(handler.Handle(media, mediaFile, option)) == nil {
handled = true
}
}
}
// Save File
if !handled {
scope.Err(media.Store(media.URL(), option, mediaFile))
}
}
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) {
if db.Callback().Create().Get("media:save_and_crop") == nil {
db.Callback().Create().After("gorm:after_create").Register("media:save_and_crop", saveAndCropImage(true))
}
if db.Callback().Update().Get("media:save_and_crop") == nil {
db.Callback().Update().Before("gorm:before_update").Register("media:save_and_crop", saveAndCropImage(false))
}
}