github.com/gogf/gf/v2@v2.7.4/util/gvalid/gvalid.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  // Package gvalid implements powerful and useful data/form validation functionality.
     8  package gvalid
     9  
    10  import (
    11  	"context"
    12  	"reflect"
    13  	"regexp"
    14  	"strings"
    15  
    16  	"github.com/gogf/gf/v2/internal/intlog"
    17  	"github.com/gogf/gf/v2/text/gregex"
    18  	"github.com/gogf/gf/v2/util/gtag"
    19  )
    20  
    21  // CustomMsg is the custom error message type,
    22  // like: map[field] => string|map[rule]string
    23  type CustomMsg = map[string]interface{}
    24  
    25  // fieldRule defined the alias name and rule string for specified field.
    26  type fieldRule struct {
    27  	Name      string       // Alias name for the field.
    28  	Rule      string       // Rule string like: "max:6"
    29  	IsMeta    bool         // Is this rule is from gmeta.Meta, which marks it as whole struct rule.
    30  	FieldKind reflect.Kind // Original kind of struct field, which is used for parameter type checks.
    31  	FieldType reflect.Type // Type of struct field, which is used for parameter type checks.
    32  }
    33  
    34  // iNoValidation is an interface that marks current struct not validated by package `gvalid`.
    35  type iNoValidation interface {
    36  	NoValidation()
    37  }
    38  
    39  const (
    40  	singleRulePattern         = `^([\w-]+):{0,1}(.*)` // regular expression pattern for single validation rule.
    41  	internalRulesErrRuleName  = "InvalidRules"        // rule name for internal invalid rules validation error.
    42  	internalParamsErrRuleName = "InvalidParams"       // rule name for internal invalid params validation error.
    43  	internalObjectErrRuleName = "InvalidObject"       // rule name for internal invalid object validation error.
    44  	internalErrorMapKey       = "__InternalError__"   // error map key for internal errors.
    45  	internalDefaultRuleName   = "__default__"         // default rule name for i18n error message format if no i18n message found for specified error rule.
    46  	ruleMessagePrefixForI18n  = "gf.gvalid.rule."     // prefix string for each rule configuration in i18n content.
    47  	noValidationTagName       = gtag.NoValidation     // no validation tag name for struct attribute.
    48  	ruleNameRegex             = "regex"               // the name for rule "regex"
    49  	ruleNameNotRegex          = "not-regex"           // the name for rule "not-regex"
    50  	ruleNameForeach           = "foreach"             // the name for rule "foreach"
    51  	ruleNameBail              = "bail"                // the name for rule "bail"
    52  	ruleNameCi                = "ci"                  // the name for rule "ci"
    53  	emptyJsonArrayStr         = "[]"                  // Empty json string for array type.
    54  	emptyJsonObjectStr        = "{}"                  // Empty json string for object type.
    55  	requiredRulesPrefix       = "required"            // requiredRulesPrefix specifies the rule prefix that must be validated even the value is empty (nil or empty).
    56  )
    57  
    58  var (
    59  	// defaultErrorMessages is the default error messages.
    60  	// Note that these messages are synchronized from ./i18n/en/validation.toml .
    61  	defaultErrorMessages = map[string]string{
    62  		internalDefaultRuleName: "The {field} value `{value}` is invalid",
    63  	}
    64  
    65  	// structTagPriority specifies the validation tag priority array.
    66  	structTagPriority = []string{gtag.Valid, gtag.ValidShort}
    67  
    68  	// aliasNameTagPriority specifies the alias tag priority array.
    69  	aliasNameTagPriority = []string{gtag.Param, gtag.ParamShort}
    70  
    71  	// all internal error keys.
    72  	internalErrKeyMap = map[string]string{
    73  		internalRulesErrRuleName:  internalRulesErrRuleName,
    74  		internalParamsErrRuleName: internalParamsErrRuleName,
    75  		internalObjectErrRuleName: internalObjectErrRuleName,
    76  	}
    77  	// regular expression object for single rule
    78  	// which is compiled just once and of repeatable usage.
    79  	ruleRegex, _ = regexp.Compile(singleRulePattern)
    80  
    81  	// decorativeRuleMap defines all rules that are just marked rules which have neither functional meaning
    82  	// nor error messages.
    83  	decorativeRuleMap = map[string]bool{
    84  		ruleNameForeach: true,
    85  		ruleNameBail:    true,
    86  		ruleNameCi:      true,
    87  	}
    88  )
    89  
    90  // ParseTagValue parses one sequence tag to field, rule and error message.
    91  // The sequence tag is like: [alias@]rule[...#msg...]
    92  func ParseTagValue(tag string) (field, rule, msg string) {
    93  	// Complete sequence tag.
    94  	// Example: name@required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致
    95  	match, _ := gregex.MatchString(`\s*((\w+)\s*@){0,1}\s*([^#]+)\s*(#\s*(.*)){0,1}\s*`, tag)
    96  	if len(match) > 5 {
    97  		msg = strings.TrimSpace(match[5])
    98  		rule = strings.TrimSpace(match[3])
    99  		field = strings.TrimSpace(match[2])
   100  	} else {
   101  		intlog.Errorf(context.TODO(), `invalid validation tag value: %s`, tag)
   102  	}
   103  	return
   104  }
   105  
   106  // GetTags returns the validation tags.
   107  func GetTags() []string {
   108  	return structTagPriority
   109  }