gvalid_error.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. package gvalid
  7. import (
  8. "github.com/gogf/gf/errors/gcode"
  9. "github.com/gogf/gf/errors/gerror"
  10. "github.com/gogf/gf/text/gregex"
  11. "github.com/gogf/gf/text/gstr"
  12. "strings"
  13. )
  14. // Error is the validation error for validation result.
  15. type Error interface {
  16. Code() gcode.Code
  17. Current() error
  18. Error() string
  19. FirstItem() (key string, messages map[string]string)
  20. FirstRule() (rule string, err string)
  21. FirstString() (err string)
  22. Items() (items []map[string]map[string]string)
  23. Map() map[string]string
  24. Maps() map[string]map[string]string
  25. String() string
  26. Strings() (errs []string)
  27. }
  28. // validationError is the validation error for validation result.
  29. type validationError struct {
  30. code gcode.Code // Error code.
  31. rules []fieldRule // Rules by sequence, which is used for keeping error sequence.
  32. errors map[string]map[string]string // Error map:map[field]map[rule]message
  33. firstKey string // The first error rule key(empty in default).
  34. firstItem map[string]string // The first error rule value(nil in default).
  35. }
  36. // newError creates and returns a validation error.
  37. func newError(code gcode.Code, rules []fieldRule, errors map[string]map[string]string) *validationError {
  38. for field, m := range errors {
  39. for k, v := range m {
  40. v = strings.Replace(v, ":attribute", field, -1)
  41. v, _ = gregex.ReplaceString(`\s{2,}`, ` `, v)
  42. v = gstr.Trim(v)
  43. m[k] = v
  44. }
  45. errors[field] = m
  46. }
  47. return &validationError{
  48. code: code,
  49. rules: rules,
  50. errors: errors,
  51. }
  52. }
  53. // newErrorStr creates and returns a validation error by string.
  54. func newErrorStr(key, err string) *validationError {
  55. return newError(gcode.CodeInternalError, nil, map[string]map[string]string{
  56. internalErrorMapKey: {
  57. key: err,
  58. },
  59. })
  60. }
  61. // Code returns the error code of current validation error.
  62. func (e *validationError) Code() gcode.Code {
  63. if e == nil {
  64. return gcode.CodeNil
  65. }
  66. return e.code
  67. }
  68. // Map returns the first error message as map.
  69. func (e *validationError) Map() map[string]string {
  70. if e == nil {
  71. return map[string]string{}
  72. }
  73. _, m := e.FirstItem()
  74. return m
  75. }
  76. // Maps returns all error messages as map.
  77. func (e *validationError) Maps() map[string]map[string]string {
  78. if e == nil {
  79. return nil
  80. }
  81. return e.errors
  82. }
  83. // Items retrieves and returns error items array in sequence if possible,
  84. // or else it returns error items with no sequence .
  85. func (e *validationError) Items() (items []map[string]map[string]string) {
  86. if e == nil {
  87. return []map[string]map[string]string{}
  88. }
  89. items = make([]map[string]map[string]string, 0)
  90. // By sequence.
  91. if len(e.rules) > 0 {
  92. for _, v := range e.rules {
  93. if errorItemMap, ok := e.errors[v.Name]; ok {
  94. items = append(items, map[string]map[string]string{
  95. v.Name: errorItemMap,
  96. })
  97. }
  98. }
  99. return items
  100. }
  101. // No sequence.
  102. for name, errorRuleMap := range e.errors {
  103. items = append(items, map[string]map[string]string{
  104. name: errorRuleMap,
  105. })
  106. }
  107. return
  108. }
  109. // FirstItem returns the field name and error messages for the first validation rule error.
  110. func (e *validationError) FirstItem() (key string, messages map[string]string) {
  111. if e == nil {
  112. return "", map[string]string{}
  113. }
  114. if e.firstItem != nil {
  115. return e.firstKey, e.firstItem
  116. }
  117. // By sequence.
  118. if len(e.rules) > 0 {
  119. for _, v := range e.rules {
  120. if errorItemMap, ok := e.errors[v.Name]; ok {
  121. e.firstKey = v.Name
  122. e.firstItem = errorItemMap
  123. return v.Name, errorItemMap
  124. }
  125. }
  126. }
  127. // No sequence.
  128. for k, m := range e.errors {
  129. e.firstKey = k
  130. e.firstItem = m
  131. return k, m
  132. }
  133. return "", nil
  134. }
  135. // FirstRule returns the first error rule and message string.
  136. func (e *validationError) FirstRule() (rule string, err string) {
  137. if e == nil {
  138. return "", ""
  139. }
  140. // By sequence.
  141. if len(e.rules) > 0 {
  142. for _, v := range e.rules {
  143. if errorItemMap, ok := e.errors[v.Name]; ok {
  144. for _, ruleItem := range strings.Split(v.Rule, "|") {
  145. array := strings.Split(ruleItem, ":")
  146. ruleItem = strings.TrimSpace(array[0])
  147. if err, ok = errorItemMap[ruleItem]; ok {
  148. return ruleItem, err
  149. }
  150. }
  151. }
  152. }
  153. }
  154. // No sequence.
  155. for _, errorItemMap := range e.errors {
  156. for k, v := range errorItemMap {
  157. return k, v
  158. }
  159. }
  160. return "", ""
  161. }
  162. // FirstString returns the first error message as string.
  163. // Note that the returned message might be different if it has no sequence.
  164. func (e *validationError) FirstString() (err string) {
  165. if e == nil {
  166. return ""
  167. }
  168. _, err = e.FirstRule()
  169. return
  170. }
  171. // Current is alis of FirstString, which implements interface gerror.ApiCurrent.
  172. func (e *validationError) Current() error {
  173. if e == nil {
  174. return nil
  175. }
  176. _, err := e.FirstRule()
  177. return gerror.NewCode(e.code, err)
  178. }
  179. // String returns all error messages as string, multiple error messages joined using char ';'.
  180. func (e *validationError) String() string {
  181. if e == nil {
  182. return ""
  183. }
  184. return strings.Join(e.Strings(), "; ")
  185. }
  186. // Error implements interface of error.Error.
  187. func (e *validationError) Error() string {
  188. if e == nil {
  189. return ""
  190. }
  191. return e.String()
  192. }
  193. // Strings returns all error messages as string array.
  194. func (e *validationError) Strings() (errs []string) {
  195. if e == nil {
  196. return []string{}
  197. }
  198. errs = make([]string, 0)
  199. // By sequence.
  200. if len(e.rules) > 0 {
  201. for _, v := range e.rules {
  202. if errorItemMap, ok := e.errors[v.Name]; ok {
  203. // validation error checks.
  204. for _, ruleItem := range strings.Split(v.Rule, "|") {
  205. ruleItem = strings.TrimSpace(strings.Split(ruleItem, ":")[0])
  206. if err, ok := errorItemMap[ruleItem]; ok {
  207. errs = append(errs, err)
  208. }
  209. }
  210. // internal error checks.
  211. for k, _ := range internalErrKeyMap {
  212. if err, ok := errorItemMap[k]; ok {
  213. errs = append(errs, err)
  214. }
  215. }
  216. }
  217. }
  218. return errs
  219. }
  220. // No sequence.
  221. for _, errorItemMap := range e.errors {
  222. for _, err := range errorItemMap {
  223. errs = append(errs, err)
  224. }
  225. }
  226. return
  227. }