From e0db3c87cfdde93f44564ca9d28ed649950dd11f Mon Sep 17 00:00:00 2001 From: John Guo Date: Tue, 9 Nov 2021 14:31:16 +0800 Subject: [PATCH] improve RuleFunc for package gvalid --- util/gvalid/gvalid_custom_rule.go | 46 ++++++++++++++----- util/gvalid/gvalid_validator_check_value.go | 8 +++- util/gvalid/gvalid_z_example_test.go | 14 +++--- util/gvalid/gvalid_z_unit_custom_rule_test.go | 44 +++++++++--------- 4 files changed, 69 insertions(+), 43 deletions(-) diff --git a/util/gvalid/gvalid_custom_rule.go b/util/gvalid/gvalid_custom_rule.go index 418e9f95f..63b1020b4 100644 --- a/util/gvalid/gvalid_custom_rule.go +++ b/util/gvalid/gvalid_custom_rule.go @@ -6,16 +6,29 @@ package gvalid -import "context" +import ( + "context" + "github.com/gogf/gf/v2/container/gvar" +) // RuleFunc is the custom function for data validation. -// -// The parameter `rule` specifies the validation rule string, like "required", "between:1,100", etc. -// The parameter `value` specifies the value for this rule to validate. -// The parameter `message` specifies the custom error message or configured i18n message for this rule. -// The parameter `data` specifies the `data` which is passed to the Validator. It might be a type of map/struct or a nil value. -// You can ignore the parameter `data` if you do not really need it in your custom validation rule. -type RuleFunc func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error +type RuleFunc func(ctx context.Context, in RuleFuncInput) error + +// RuleFuncInput holds the input parameters that passed to custom rule function RuleFunc. +type RuleFuncInput struct { + // Rule specifies the validation rule string, like "required", "between:1,100", etc. + Rule string + + // Message specifies the custom error message or configured i18n message for this rule. + Message string + + // Value specifies the value for this rule to validate. + Value *gvar.Var + + // Data specifies the `data` which is passed to the Validator. It might be a type of map/struct or a nil value. + // You can ignore the parameter `Data` if you do not really need it in your custom validation rule. + Data *gvar.Var +} var ( // customRuleFuncMap stores the custom rule functions. @@ -24,13 +37,22 @@ var ( ) // RegisterRule registers custom validation rule and function for package. -// It returns error if there's already the same rule registered previously. func RegisterRule(rule string, f RuleFunc) error { customRuleFuncMap[rule] = f return nil } -// DeleteRule deletes custom defined validation rule and its function from global package. -func DeleteRule(rule string) { - delete(customRuleFuncMap, rule) +// RegisterRuleByMap registers custom validation rules using map for package. +func RegisterRuleByMap(m map[string]RuleFunc) error { + for k, v := range m { + customRuleFuncMap[k] = v + } + return nil +} + +// DeleteRule deletes custom defined validation one or more rules and associated functions from global package. +func DeleteRule(rules ...string) { + for _, rule := range rules { + delete(customRuleFuncMap, rule) + } } diff --git a/util/gvalid/gvalid_validator_check_value.go b/util/gvalid/gvalid_validator_check_value.go index 36176f361..182a10d10 100644 --- a/util/gvalid/gvalid_validator_check_value.go +++ b/util/gvalid/gvalid_validator_check_value.go @@ -8,6 +8,7 @@ package gvalid import ( "context" + "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" @@ -133,7 +134,12 @@ func (v *Validator) doCheckValue(ctx context.Context, input doCheckValueInput) E if customRuleFunc != nil { // It checks custom validation rules with most priority. message := v.getErrorMessageByRule(ctx, ruleKey, customMsgMap) - if err := customRuleFunc(ctx, ruleItems[index], input.Value, message, input.DataRaw); err != nil { + if err := customRuleFunc(ctx, RuleFuncInput{ + Rule: ruleItems[index], + Message: message, + Value: gvar.New(input.Value), + Data: gvar.New(input.DataRaw), + }); err != nil { match = false errorMsgArray[ruleKey] = err.Error() } else { diff --git a/util/gvalid/gvalid_z_example_test.go b/util/gvalid/gvalid_z_example_test.go index f163b1b56..c9c8c0128 100644 --- a/util/gvalid/gvalid_z_example_test.go +++ b/util/gvalid/gvalid_z_example_test.go @@ -127,17 +127,17 @@ func ExampleRegisterRule() { } rule := "unique-name" - gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error { + gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error { var ( - id = data.(*User).Id - name = gconv.String(value) + id = in.Data.Val().(*User).Id + name = gconv.String(in.Value) ) n, err := g.Model("user").Where("id != ? and name = ?", id, name).Count() if err != nil { return err } if n > 0 { - return errors.New(message) + return errors.New(in.Message) } return nil }) @@ -149,8 +149,8 @@ func ExampleRegisterRule() { func ExampleRegisterRule_OverwriteRequired() { rule := "required" - gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error { - reflectValue := reflect.ValueOf(value) + gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error { + reflectValue := reflect.ValueOf(in.Value.Val()) if reflectValue.Kind() == reflect.Ptr { reflectValue = reflectValue.Elem() } @@ -171,7 +171,7 @@ func ExampleRegisterRule_OverwriteRequired() { isEmpty = reflectValue.Len() == 0 } if isEmpty { - return errors.New(message) + return errors.New(in.Message) } return nil }) diff --git a/util/gvalid/gvalid_z_unit_custom_rule_test.go b/util/gvalid/gvalid_z_unit_custom_rule_test.go index 75285813c..cd27fb46c 100644 --- a/util/gvalid/gvalid_z_unit_custom_rule_test.go +++ b/util/gvalid/gvalid_z_unit_custom_rule_test.go @@ -12,8 +12,6 @@ import ( "testing" "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/util/gconv" - "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/gvalid" ) @@ -22,14 +20,14 @@ func Test_CustomRule1(t *testing.T) { rule := "custom" err := gvalid.RegisterRule( rule, - func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error { - pass := gconv.String(value) + func(ctx context.Context, in gvalid.RuleFuncInput) error { + pass := in.Value.String() if len(pass) != 6 { - return errors.New(message) + return errors.New(in.Message) } - m := gconv.Map(data) + m := in.Data.Map() if m["data"] != pass { - return errors.New(message) + return errors.New(in.Message) } return nil }, @@ -71,10 +69,10 @@ func Test_CustomRule1(t *testing.T) { func Test_CustomRule2(t *testing.T) { rule := "required-map" - err := gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error { - m := gconv.Map(value) + err := gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error { + m := in.Value.Map() if len(m) == 0 { - return errors.New(message) + return errors.New(in.Message) } return nil }) @@ -115,12 +113,12 @@ func Test_CustomRule2(t *testing.T) { func Test_CustomRule_AllowEmpty(t *testing.T) { rule := "allow-empty-str" - err := gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error { - s := gconv.String(value) + err := gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error { + s := in.Value.String() if len(s) == 0 || s == "gf" { return nil } - return errors.New(message) + return errors.New(in.Message) }) gtest.Assert(err, nil) // Check. @@ -160,13 +158,13 @@ func Test_CustomRule_AllowEmpty(t *testing.T) { func TestValidator_RuleFunc(t *testing.T) { ruleName := "custom_1" - ruleFunc := func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error { - pass := gconv.String(value) + ruleFunc := func(ctx context.Context, in gvalid.RuleFuncInput) error { + pass := in.Value.String() if len(pass) != 6 { - return errors.New(message) + return errors.New(in.Message) } - if m := gconv.Map(data); m["data"] != pass { - return errors.New(message) + if m := in.Data.Map(); m["data"] != pass { + return errors.New(in.Message) } return nil } @@ -214,13 +212,13 @@ func TestValidator_RuleFunc(t *testing.T) { func TestValidator_RuleFuncMap(t *testing.T) { ruleName := "custom_1" - ruleFunc := func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error { - pass := gconv.String(value) + ruleFunc := func(ctx context.Context, in gvalid.RuleFuncInput) error { + pass := in.Value.String() if len(pass) != 6 { - return errors.New(message) + return errors.New(in.Message) } - if m := gconv.Map(data); m["data"] != pass { - return errors.New(message) + if m := in.Data.Map(); m["data"] != pass { + return errors.New(in.Message) } return nil }