func move(db *gorm.DB, value sortingInterface, pos int) error { clone := db for _, field := range db.NewScope(value).PrimaryFields() { if field.DBName != "id" { clone = clone.Where(fmt.Sprintf("%s = ?", field.DBName), field.Field.Interface()) } } currentPos := value.GetPosition() if pos > 0 { if results := clone.Model(newModel(value)). Where("position > ? AND position <= ?", currentPos, currentPos+pos). UpdateColumn("position", gorm.Expr("position - ?", 1)); results.Error == nil { value.SetPosition(currentPos + int(results.RowsAffected)) return clone.Model(value).UpdateColumn("position", gorm.Expr("position + ?", results.RowsAffected)).Error } } else if pos < 0 { if results := clone.Model(newModel(value)). Where("position < ? AND position >= ?", currentPos, currentPos+pos). UpdateColumn("position", gorm.Expr("position + ?", 1)); results.Error == nil { value.SetPosition(currentPos - int(results.RowsAffected)) return clone.Model(value).UpdateColumn("position", gorm.Expr("position - ?", results.RowsAffected)).Error } } return nil }
func New(db *gorm.DB) *Publish { tableHandler := gorm.DefaultTableNameHandler gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string { tableName := tableHandler(db, defaultTableName) if db != nil { if IsPublishableModel(db.Value) { // Set join table handler typ := utils.ModelType(db.Value) if !injectedJoinTableHandler[typ] { injectedJoinTableHandler[typ] = true scope := db.NewScope(db.Value) for _, field := range scope.GetModelStruct().StructFields { if many2many := utils.ParseTagOption(field.Tag.Get("gorm"))["MANY2MANY"]; many2many != "" { db.SetJoinTableHandler(db.Value, field.Name, &publishJoinTableHandler{}) db.AutoMigrate(db.Value) } } } var forceDraftTable bool if forceDraftTable, ok := db.Get("publish:force_draft_table"); ok { if forceMode, ok := forceDraftTable.(bool); ok && forceMode { forceDraftTable = true } } if IsDraftMode(db) || forceDraftTable { return DraftTableName(tableName) } } } return tableName } db.AutoMigrate(&PublishEvent{}) db.Callback().Create().Before("gorm:begin_transaction").Register("publish:set_table_to_draft", setTableAndPublishStatus(true)) db.Callback().Create().Before("gorm:commit_or_rollback_transaction"). Register("publish:sync_to_production_after_create", syncCreateFromProductionToDraft) db.Callback().Create().Before("gorm:commit_or_rollback_transaction").Register("gorm:create_publish_event", createPublishEvent) db.Callback().Delete().Before("gorm:begin_transaction").Register("publish:set_table_to_draft", setTableAndPublishStatus(true)) db.Callback().Delete().Replace("gorm:delete", deleteScope) db.Callback().Delete().Before("gorm:commit_or_rollback_transaction"). Register("publish:sync_to_production_after_delete", syncDeleteFromProductionToDraft) db.Callback().Delete().Before("gorm:commit_or_rollback_transaction").Register("gorm:create_publish_event", createPublishEvent) db.Callback().Update().Before("gorm:begin_transaction").Register("publish:set_table_to_draft", setTableAndPublishStatus(true)) db.Callback().Update().Before("gorm:commit_or_rollback_transaction"). Register("publish:sync_to_production", syncUpdateFromProductionToDraft) db.Callback().Update().Before("gorm:commit_or_rollback_transaction").Register("gorm:create_publish_event", createPublishEvent) db.Callback().RowQuery().Register("publish:set_table_in_draft_mode", setTableAndPublishStatus(false)) db.Callback().Query().Before("gorm:query").Register("publish:set_table_in_draft_mode", setTableAndPublishStatus(false)) return &Publish{DB: db} }
func AddErrorForColumn(db *gorm.DB, resource interface{}, column, err string) { var validationErrors = GetErrors(db) var scope = db.NewScope(resource) key := fmt.Sprintf("%v_%v_%v", scope.GetModelStruct().ModelType.Name(), scope.PrimaryKeyValue(), column) validationErrors[key] = append(validationErrors[key], err) db.InstantSet(settingKey, validationErrors).Error = fmt.Errorf("RecordInvalid: %v", err) }
func (*PersonAddress) Add(handler gorm.JoinTableHandlerInterface, db *gorm.DB, foreignValue interface{}, associationValue interface{}) error { return db.Where(map[string]interface{}{ "person_id": db.NewScope(foreignValue).PrimaryKeyValue(), "address_id": db.NewScope(associationValue).PrimaryKeyValue(), }).Assign(map[string]interface{}{ "person_id": foreignValue, "address_id": associationValue, "deleted_at": gorm.Expr("NULL"), }).FirstOrCreate(&PersonAddress{}).Error }
// GetChangeLogs get state change logs func GetStateChangeLogs(model interface{}, db *gorm.DB) []StateChangeLog { var ( changelogs []StateChangeLog scope = db.NewScope(model) ) db.Where("refer_table = ? AND refer_id = ?", scope.TableName(), GenerateReferenceKey(model, db)).Find(&changelogs) return changelogs }
// GenerateReferenceKey generate reference key used for change log func GenerateReferenceKey(model interface{}, db *gorm.DB) string { var ( scope = db.NewScope(model) primaryValues []string ) for _, field := range scope.PrimaryFields() { primaryValues = append(primaryValues, fmt.Sprint(field.Field.Interface())) } return strings.Join(primaryValues, "::") }
func getCurrentUser(db *gorm.DB) (string, bool) { if user, hasUser := db.Get("qor:current_user"); hasUser { var currentUser string if primaryField := db.NewScope(user).PrimaryField(); primaryField != nil { currentUser = fmt.Sprintf("%v", primaryField.Field.Interface()) } else { currentUser = fmt.Sprintf("%v", user) } return currentUser, true } return "", false }
func move(db *gorm.DB, value sortingInterface, pos int) (err error) { var startedTransaction bool var tx = db.Set("publish:publish_event", true) if t := tx.Begin(); t.Error == nil { startedTransaction = true tx = t } scope := db.NewScope(value) for _, field := range scope.PrimaryFields() { if field.DBName != "id" { tx = tx.Where(fmt.Sprintf("%s = ?", field.DBName), field.Field.Interface()) } } currentPos := value.GetPosition() var results *gorm.DB if pos > 0 { results = tx.Model(newModel(value)). Where("position > ? AND position <= ?", currentPos, currentPos+pos). UpdateColumn("position", gorm.Expr("position - ?", 1)) } else { results = tx.Model(newModel(value)). Where("position < ? AND position >= ?", currentPos, currentPos+pos). UpdateColumn("position", gorm.Expr("position + ?", 1)) } if err = results.Error; err == nil { var rowsAffected = int(results.RowsAffected) if pos < 0 { rowsAffected = -rowsAffected } value.SetPosition(currentPos + rowsAffected) err = tx.Model(value).UpdateColumn("position", gorm.Expr("position + ?", rowsAffected)).Error } // Create Publish Event createPublishEvent(tx, value) if startedTransaction { if err == nil { tx.Commit() } else { tx.Rollback() } } return err }
func (e changedSortingPublishEvent) Discard(db *gorm.DB, event publish.PublishEventInterface) error { if event, ok := event.(*publish.PublishEvent); ok { scope := db.NewScope("") if err := json.Unmarshal([]byte(event.Argument), &e); err == nil { var conditions []string originalTable := scope.Quote(publish.OriginalTableName(e.Table)) draftTable := scope.Quote(publish.DraftTableName(e.Table)) for _, primaryKey := range e.PrimaryKeys { conditions = append(conditions, fmt.Sprintf("%v.%v = %v.%v", originalTable, primaryKey, draftTable, primaryKey)) } sql := fmt.Sprintf("UPDATE %v SET position = (select position FROM %v WHERE %v);", draftTable, originalTable, strings.Join(conditions, " AND ")) return db.Exec(sql).Error } else { return err } } return errors.New("invalid publish event") }
func (pb Publish) search(db *gorm.DB, res *admin.Resource, ids [][]string) *gorm.DB { var primaryKeys []string var primaryValues [][][]interface{} var scope = db.NewScope(res.Value) for _, primaryField := range scope.PrimaryFields() { primaryKeys = append(primaryKeys, primaryField.DBName) } for _, id := range ids { var primaryValue [][]interface{} for idx, value := range id { primaryValue = append(primaryValue, []interface{}{primaryKeys[idx], value}) } primaryValues = append(primaryValues, primaryValue) } sql := fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, primaryKeys), toQueryMarks(primaryValues)) return pb.SearchHandler(db, nil).Where(sql, toQueryValues(primaryValues)...) }
func createPublishEvent(db *gorm.DB, value interface{}) (err error) { // Create Publish Event in Draft Mode if publish.IsDraftMode(db) && publish.IsPublishableModel(value) { scope := db.NewScope(value) var sortingPublishEvent = changedSortingPublishEvent{ Table: scope.TableName(), } for _, field := range scope.PrimaryFields() { sortingPublishEvent.PrimaryKeys = append(sortingPublishEvent.PrimaryKeys, field.DBName) } var result []byte if result, err = json.Marshal(sortingPublishEvent); err == nil { err = db.New().Where("publish_status = ?", publish.DIRTY).Where(map[string]interface{}{ "name": "changed_sorting", "argument": string(result), }).Attrs(map[string]interface{}{ "publish_status": publish.DIRTY, "description": "Changed sort order for " + scope.GetModelStruct().ModelType.Name(), }).FirstOrCreate(&publish.PublishEvent{}).Error } } return }
// Trigger trigger an event func (sm *StateMachine) Trigger(name string, value Stater, tx *gorm.DB, notes ...string) error { var ( newTx *gorm.DB stateWas = value.GetState() ) if tx != nil { newTx = tx.New() } if stateWas == "" { stateWas = sm.initialState value.SetState(sm.initialState) } if event := sm.events[name]; event != nil { var matchedTransitions []*EventTransition for _, transition := range event.transitions { var validFrom = len(transition.froms) == 0 if len(transition.froms) > 0 { for _, from := range transition.froms { if from == stateWas { validFrom = true } } } if validFrom { matchedTransitions = append(matchedTransitions, transition) } } if len(matchedTransitions) == 1 { transition := matchedTransitions[0] // State: exit if state, ok := sm.states[stateWas]; ok { for _, exit := range state.exits { if err := exit(value, newTx); err != nil { return err } } } // Transition: before for _, before := range transition.befores { if err := before(value, newTx); err != nil { return err } } value.SetState(transition.to) // State: enter if state, ok := sm.states[transition.to]; ok { for _, enter := range state.enters { if err := enter(value, newTx); err != nil { value.SetState(stateWas) return err } } } // Transition: after for _, after := range transition.afters { if err := after(value, newTx); err != nil { value.SetState(stateWas) return err } } if newTx != nil { scope := newTx.NewScope(value) log := StateChangeLog{ ReferTable: scope.TableName(), ReferID: GenerateReferenceKey(value, tx), From: stateWas, To: transition.to, Note: strings.Join(notes, ""), } return newTx.Save(&log).Error } return nil } } return fmt.Errorf("failed to perform event %s from state %s", name, stateWas) }