form.go 3.7 KB

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