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