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  }