form.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package form
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "github.com/flamego/binding"
  7. "github.com/unknwon/com"
  8. "gogs.io/gogs/internal/email"
  9. "gogs.io/gogs/internal/lazyregexp"
  10. )
  11. const ErrAlphaDashDotSlash = "AlphaDashDotSlashError"
  12. var AlphaDashDotSlashPattern = lazyregexp.New("[^\\d\\w-_\\./]")
  13. func init() {
  14. binding.SetNameMapper(com.ToSnakeCase)
  15. binding.AddRule(&binding.Rule{
  16. IsMatch: func(rule string) bool {
  17. return rule == "AlphaDashDotSlash"
  18. },
  19. IsValid: func(errs binding.Errors, name string, v any) (bool, binding.Errors) {
  20. if AlphaDashDotSlashPattern.MatchString(fmt.Sprintf("%v", v)) {
  21. errs.Add([]string{name}, ErrAlphaDashDotSlash, "AlphaDashDotSlash")
  22. return false, errs
  23. }
  24. return true, errs
  25. },
  26. })
  27. }
  28. // Assign assign form values back to the template data.
  29. func Assign(form any, data map[string]any) {
  30. typ := reflect.TypeOf(form)
  31. val := reflect.ValueOf(form)
  32. if typ.Kind() == reflect.Ptr {
  33. typ = typ.Elem()
  34. val = val.Elem()
  35. }
  36. for i := 0; i < typ.NumField(); i++ {
  37. field := typ.Field(i)
  38. fieldName := field.Tag.Get("form")
  39. // Allow ignored fields in the struct
  40. if fieldName == "-" {
  41. continue
  42. } else if fieldName == "" {
  43. fieldName = com.ToSnakeCase(field.Name)
  44. }
  45. data[fieldName] = val.Field(i).Interface()
  46. }
  47. }
  48. func getRuleBody(field reflect.StructField, prefix string) string {
  49. for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
  50. if strings.HasPrefix(rule, prefix) {
  51. return rule[len(prefix) : len(rule)-1]
  52. }
  53. }
  54. return ""
  55. }
  56. func getSize(field reflect.StructField) string {
  57. return getRuleBody(field, "Size(")
  58. }
  59. func getMinSize(field reflect.StructField) string {
  60. return getRuleBody(field, "MinSize(")
  61. }
  62. func getMaxSize(field reflect.StructField) string {
  63. return getRuleBody(field, "MaxSize(")
  64. }
  65. func getInclude(field reflect.StructField) string {
  66. return getRuleBody(field, "Include(")
  67. }
  68. func validate(errs binding.Errors, data map[string]any, l email.Translator) binding.Errors {
  69. if errs.Len() == 0 {
  70. return errs
  71. }
  72. data["HasError"] = true
  73. typ := reflect.TypeOf(errs[0])
  74. if typ == nil {
  75. return errs
  76. }
  77. for i := 0; i < typ.NumField(); i++ {
  78. field := typ.Field(i)
  79. if errs[0].FieldNames[0] == field.Name {
  80. data["Err_"+field.Name] = true
  81. trName := field.Tag.Get("locale")
  82. if trName == "" {
  83. trName = l.Tr("form." + field.Name)
  84. } else {
  85. trName = l.Tr(trName)
  86. }
  87. switch errs[0].Classification {
  88. case binding.ERR_REQUIRED:
  89. data["ErrorMsg"] = trName + l.Tr("form.require_error")
  90. case binding.ERR_ALPHA_DASH:
  91. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
  92. case binding.ERR_ALPHA_DASH_DOT:
  93. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
  94. case ErrAlphaDashDotSlash:
  95. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_slash_error")
  96. case binding.ERR_SIZE:
  97. data["ErrorMsg"] = trName + l.Tr("form.size_error", getSize(field))
  98. case binding.ERR_MIN_SIZE:
  99. data["ErrorMsg"] = trName + l.Tr("form.min_size_error", getMinSize(field))
  100. case binding.ERR_MAX_SIZE:
  101. data["ErrorMsg"] = trName + l.Tr("form.max_size_error", getMaxSize(field))
  102. case binding.ERR_EMAIL:
  103. data["ErrorMsg"] = trName + l.Tr("form.email_error")
  104. case binding.ERR_URL:
  105. data["ErrorMsg"] = trName + l.Tr("form.url_error")
  106. case binding.ERR_INCLUDE:
  107. data["ErrorMsg"] = trName + l.Tr("form.include_error", getInclude(field))
  108. default:
  109. data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
  110. }
  111. return errs
  112. }
  113. }
  114. return errs
  115. }