goyave.dev/goyave/v4@v4.4.11/validation/placeholder.go (about) 1 package validation 2 3 import ( 4 "sort" 5 "strings" 6 "time" 7 8 "goyave.dev/goyave/v4/lang" 9 ) 10 11 // Placeholder function defining a placeholder in a validation message. 12 // This function should return the value to replace the placeholder with. 13 type Placeholder func(fieldName string, language string, ctx *Context) string 14 15 var placeholders = map[string]Placeholder{} 16 var sortedKeys = []string{} 17 18 // SetPlaceholder sets the replacer function for the given placeholder. 19 // If a placeholder with this name already exists, the latter will be overridden. 20 // 21 // validation.SetPlaceholder("min", func(field string, rule string, parameters []string, language string) string { 22 // return parameters[0] // Replace ":min" by the first parameter in the rule definition 23 // }) 24 func SetPlaceholder(placeholderName string, replacer Placeholder) { 25 key := ":" + placeholderName 26 placeholders[key] = replacer 27 28 // Sort keys to process placeholders in order. 29 // Needed to avoid conflict between "values" and "value" for example. 30 sortedKeys = append(sortedKeys, key) 31 sort.Sort(sort.Reverse(sort.StringSlice(sortedKeys))) 32 } 33 34 func processPlaceholders(fieldName string, originalMessage string, language string, ctx *Context) string { 35 if i := strings.LastIndex(fieldName, "."); i != -1 { 36 fieldName = fieldName[i+1:] 37 } 38 fieldName = strings.TrimSuffix(fieldName, "[]") 39 message := originalMessage 40 for _, placeholder := range sortedKeys { 41 if strings.Contains(originalMessage, placeholder) { 42 replacer := placeholders[placeholder] 43 message = strings.ReplaceAll(message, placeholder, replacer(fieldName, language, ctx)) 44 } 45 } 46 return message 47 } 48 49 func replaceField(field, language string) string { 50 entry := "validation.fields." + field 51 attr := lang.Get(language, entry) 52 if attr == entry { 53 return field 54 } 55 return attr 56 } 57 58 func simpleParameterPlaceholder(_ string, _ string, ctx *Context) string { 59 return ctx.Rule.Params[0] 60 } 61 62 func datePlaceholder(index int, parameters []string, language string) string { 63 _, err := time.Parse("2006-01-02T15:04:05", parameters[index]) 64 if err != nil { 65 // Not a date, may be a field 66 return replaceField(parameters[index], language) 67 } 68 return parameters[index] 69 } 70 71 func init() { 72 SetPlaceholder("field", func(field string, language string, ctx *Context) string { 73 return replaceField(field, language) 74 }) 75 SetPlaceholder("value", simpleParameterPlaceholder) 76 SetPlaceholder("min", simpleParameterPlaceholder) 77 SetPlaceholder("max", func(field string, language string, ctx *Context) string { 78 index := 0 79 if strings.Contains(ctx.Rule.Name, "between") { 80 index = 1 81 } 82 return ctx.Rule.Params[index] 83 }) 84 SetPlaceholder("other", func(field string, language string, ctx *Context) string { 85 return replaceField(ctx.Rule.Params[0], language) 86 }) 87 SetPlaceholder("values", func(field string, language string, ctx *Context) string { 88 return strings.Join(ctx.Rule.Params, ", ") 89 }) 90 SetPlaceholder("version", func(field string, language string, ctx *Context) string { 91 if len(ctx.Rule.Params) > 0 { 92 return "v" + ctx.Rule.Params[0] 93 } 94 return "" 95 }) 96 SetPlaceholder("date", func(field string, language string, ctx *Context) string { 97 return datePlaceholder(0, ctx.Rule.Params, language) 98 }) 99 SetPlaceholder("max_date", func(field string, language string, ctx *Context) string { 100 return datePlaceholder(1, ctx.Rule.Params, language) 101 }) 102 }