Files
gf/util/gvalid/gvalid_error.go

190 lines
4.3 KiB
Go
Raw Normal View History

// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gvalid
2020-05-10 16:48:00 +08:00
import (
"errors"
2020-05-10 16:48:00 +08:00
"github.com/gogf/gf/text/gregex"
"strings"
)
2020-05-10 16:48:00 +08:00
// Error is the validation error for validation result.
type Error struct {
2020-05-10 16:48:00 +08:00
rules []string // Rules by sequence, which is used for keeping error sequence.
errors ErrorMap // Error map.
firstKey string // The first error rule key(nil in default).
firstItem map[string]string // The first error rule value(nil in default).
}
2020-05-10 16:48:00 +08:00
// ErrorMap is the validation error map:
// map[field]map[rule]message
type ErrorMap map[string]map[string]string
2020-05-10 16:48:00 +08:00
// newError creates and returns a validation error.
func newError(rules []string, errors map[string]map[string]string) *Error {
2020-05-10 16:48:00 +08:00
for field, m := range errors {
for k, v := range m {
v = strings.Replace(v, ":attribute", field, -1)
2020-05-10 16:48:00 +08:00
m[k], _ = gregex.ReplaceString(`\s{2,}`, ` `, v)
}
errors[field] = m
}
2019-06-19 09:06:52 +08:00
return &Error{
rules: rules,
errors: errors,
}
}
2020-05-10 16:48:00 +08:00
// newErrorStr creates and returns a validation error by string.
2018-12-14 10:09:45 +08:00
func newErrorStr(key, err string) *Error {
2020-05-10 16:48:00 +08:00
return newError(nil, map[string]map[string]string{
"__gvalid__": {
key: err,
2019-06-19 09:06:52 +08:00
},
2020-05-10 16:48:00 +08:00
})
2018-12-14 10:09:45 +08:00
}
2020-05-10 16:48:00 +08:00
// Map returns the first error message as map.
func (e *Error) Map() map[string]string {
2020-09-21 23:51:30 +08:00
if e == nil {
return map[string]string{}
}
2019-06-19 09:06:52 +08:00
_, m := e.FirstItem()
return m
}
2020-05-10 16:48:00 +08:00
// Maps returns all error messages as map.
func (e *Error) Maps() ErrorMap {
2020-09-21 23:51:30 +08:00
if e == nil {
return nil
}
2019-06-19 09:06:52 +08:00
return e.errors
}
2020-05-10 16:48:00 +08:00
// FirstItem returns the field name and error messages for the first validation rule error.
func (e *Error) FirstItem() (key string, messages map[string]string) {
2020-09-21 23:51:30 +08:00
if e == nil {
return "", map[string]string{}
}
2019-06-19 09:06:52 +08:00
if e.firstItem != nil {
return e.firstKey, e.firstItem
}
2020-05-10 16:48:00 +08:00
// By sequence.
2019-06-19 09:06:52 +08:00
if len(e.rules) > 0 {
for _, v := range e.rules {
name, _, _ := parseSequenceTag(v)
if m, ok := e.errors[name]; ok {
e.firstKey = name
e.firstItem = m
return name, m
}
}
}
2020-05-10 16:48:00 +08:00
// No sequence.
2019-06-19 09:06:52 +08:00
for k, m := range e.errors {
e.firstKey = k
e.firstItem = m
return k, m
}
return "", nil
}
2020-05-10 16:48:00 +08:00
// FirstRule returns the first error rule and message string.
func (e *Error) FirstRule() (rule string, err string) {
2020-09-21 23:51:30 +08:00
if e == nil {
return "", ""
}
2020-05-10 16:48:00 +08:00
// By sequence.
2019-06-19 09:06:52 +08:00
if len(e.rules) > 0 {
for _, v := range e.rules {
name, rule, _ := parseSequenceTag(v)
if m, ok := e.errors[name]; ok {
for _, rule := range strings.Split(rule, "|") {
array := strings.Split(rule, ":")
rule = strings.TrimSpace(array[0])
if err, ok := m[rule]; ok {
return rule, err
}
}
}
}
}
2020-05-10 16:48:00 +08:00
// No sequence.
2019-06-19 09:06:52 +08:00
for _, m := range e.errors {
for k, v := range m {
return k, v
}
}
return "", ""
}
2020-05-10 16:48:00 +08:00
// FirstString returns the first error message as string.
// Note that the returned message might be different if it has no sequence.
func (e *Error) FirstString() (err string) {
2020-09-21 23:51:30 +08:00
if e == nil {
return ""
}
2019-06-19 09:06:52 +08:00
_, err = e.FirstRule()
return
}
// Current is alis of FirstString, which implements interface gerror.ApiCurrent.
func (e *Error) Current() error {
if e == nil {
return nil
}
_, err := e.FirstRule()
return errors.New(err)
}
2020-05-10 16:48:00 +08:00
// String returns all error messages as string, multiple error messages joined using char ';'.
func (e *Error) String() string {
2020-09-21 23:51:30 +08:00
if e == nil {
return ""
}
2019-06-19 09:06:52 +08:00
return strings.Join(e.Strings(), "; ")
}
// Error implements interface of error.Error.
func (e *Error) Error() string {
2020-09-21 23:51:30 +08:00
if e == nil {
return ""
}
return e.String()
}
2020-05-10 16:48:00 +08:00
// Strings returns all error messages as string array.
func (e *Error) Strings() (errs []string) {
2020-09-21 23:51:30 +08:00
if e == nil {
return []string{}
}
2019-06-19 09:06:52 +08:00
errs = make([]string, 0)
2020-05-10 16:48:00 +08:00
// By sequence.
2019-06-19 09:06:52 +08:00
if len(e.rules) > 0 {
for _, v := range e.rules {
name, rule, _ := parseSequenceTag(v)
if m, ok := e.errors[name]; ok {
for _, rule := range strings.Split(rule, "|") {
array := strings.Split(rule, ":")
rule = strings.TrimSpace(array[0])
if err, ok := m[rule]; ok {
errs = append(errs, err)
}
}
}
}
return errs
}
2020-05-10 16:48:00 +08:00
// No sequence.
2019-06-19 09:06:52 +08:00
for _, m := range e.errors {
for _, err := range m {
errs = append(errs, err)
}
}
return
}