github.com/kotovmak/go-admin@v1.1.1/plugins/admin/modules/parameter/parameter.go (about)

     1  package parameter
     2  
     3  import (
     4  	"net/url"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/kotovmak/go-admin/plugins/admin/modules"
     9  	"github.com/kotovmak/go-admin/plugins/admin/modules/constant"
    10  	"github.com/kotovmak/go-admin/plugins/admin/modules/form"
    11  )
    12  
    13  type Parameters struct {
    14  	Page         string
    15  	PageInt      int
    16  	PageSize     string
    17  	PageSizeInt  int
    18  	SortField    string
    19  	Columns      []string
    20  	SortType     string
    21  	Animation    bool
    22  	URLPath      string
    23  	Fields       map[string][]string
    24  	OrConditions map[string]string
    25  
    26  	cacheFixedStr url.Values
    27  }
    28  
    29  const (
    30  	Page     = "__page"
    31  	PageSize = "__pageSize"
    32  	Sort     = "__sort"
    33  	SortType = "__sort_type"
    34  	Columns  = "__columns"
    35  	Prefix   = "__prefix"
    36  	Pjax     = "_pjax"
    37  
    38  	sortTypeDesc = "desc"
    39  	sortTypeAsc  = "asc"
    40  
    41  	IsAll      = "__is_all"
    42  	PrimaryKey = "__pk"
    43  
    44  	True  = "true"
    45  	False = "false"
    46  
    47  	FilterRangeParamStartSuffix = "_start__goadmin"
    48  	FilterRangeParamEndSuffix   = "_end__goadmin"
    49  	FilterParamJoinInfix        = "_goadmin_join_"
    50  	FilterParamOperatorSuffix   = "__goadmin_operator__"
    51  	FilterParamCountInfix       = "__goadmin_index__"
    52  
    53  	Separator = "__goadmin_separator__"
    54  )
    55  
    56  var operators = map[string]string{
    57  	"like": "like",
    58  	"gr":   ">",
    59  	"gq":   ">=",
    60  	"eq":   "=",
    61  	"ne":   "!=",
    62  	"le":   "<",
    63  	"lq":   "<=",
    64  	"free": "free",
    65  }
    66  
    67  var keys = []string{Page, PageSize, Sort, Columns, Prefix, Pjax, form.NoAnimationKey}
    68  
    69  func BaseParam() Parameters {
    70  	return Parameters{Page: "1", PageSize: "10", PageInt: 1, PageSizeInt: 10, Fields: make(map[string][]string)}
    71  }
    72  
    73  func GetParam(u *url.URL, defaultPageSize int, p ...string) Parameters {
    74  	values := u.Query()
    75  
    76  	primaryKey := "id"
    77  	defaultSortType := "desc"
    78  
    79  	if len(p) > 0 {
    80  		primaryKey = p[0]
    81  		defaultSortType = p[1]
    82  	}
    83  
    84  	page := getDefault(values, Page, "1")
    85  	pageSize := getDefault(values, PageSize, strconv.Itoa(defaultPageSize))
    86  	sortField := getDefault(values, Sort, primaryKey)
    87  	sortType := getDefault(values, SortType, defaultSortType)
    88  	columns := getDefault(values, Columns, "")
    89  
    90  	animation := true
    91  	if values.Get(form.NoAnimationKey) == "true" {
    92  		animation = false
    93  	}
    94  
    95  	fields := make(map[string][]string)
    96  
    97  	for key, value := range values {
    98  		if !modules.InArray(keys, key) && len(value) > 0 && value[0] != "" {
    99  			if key == SortType {
   100  				if value[0] != sortTypeDesc && value[0] != sortTypeAsc {
   101  					fields[key] = []string{sortTypeDesc}
   102  				}
   103  			} else {
   104  				if strings.Contains(key, FilterParamOperatorSuffix) &&
   105  					values.Get(strings.ReplaceAll(key, FilterParamOperatorSuffix, "")) == "" {
   106  					continue
   107  				}
   108  				fields[strings.ReplaceAll(key, "[]", "")] = value
   109  			}
   110  		}
   111  	}
   112  
   113  	columnsArr := make([]string, 0)
   114  	if columns != "" {
   115  		columns, _ = url.QueryUnescape(columns)
   116  		columnsArr = strings.Split(columns, ",")
   117  	}
   118  
   119  	pageInt, _ := strconv.Atoi(page)
   120  	pageSizeInt, _ := strconv.Atoi(pageSize)
   121  
   122  	return Parameters{
   123  		Page:         page,
   124  		PageSize:     pageSize,
   125  		PageSizeInt:  pageSizeInt,
   126  		PageInt:      pageInt,
   127  		URLPath:      u.Path,
   128  		SortField:    sortField,
   129  		SortType:     sortType,
   130  		Fields:       fields,
   131  		OrConditions: map[string]string{},
   132  		Animation:    animation,
   133  		Columns:      columnsArr,
   134  	}
   135  }
   136  
   137  func GetParamFromURL(urlStr string, defaultPageSize int, defaultSortType, primaryKey string) Parameters {
   138  
   139  	u, err := url.Parse(urlStr)
   140  
   141  	if err != nil {
   142  		return BaseParam()
   143  	}
   144  
   145  	return GetParam(u, defaultPageSize, primaryKey, defaultSortType)
   146  }
   147  
   148  func (param Parameters) WithPKs(id ...string) Parameters {
   149  	param.Fields[PrimaryKey] = []string{strings.Join(id, ",")}
   150  	return param
   151  }
   152  
   153  func (param Parameters) PKs() []string {
   154  	pk := param.GetFieldValue(PrimaryKey)
   155  	if pk == "" {
   156  		return []string{}
   157  	}
   158  	return strings.Split(param.GetFieldValue(PrimaryKey), ",")
   159  }
   160  
   161  func (param Parameters) DeletePK() Parameters {
   162  	delete(param.Fields, PrimaryKey)
   163  	return param
   164  }
   165  
   166  func (param Parameters) PK() string {
   167  	pks := param.PKs()
   168  	if len(pks) > 0 {
   169  		return pks[0]
   170  	}
   171  	return ""
   172  }
   173  
   174  func (param Parameters) IsAll() bool {
   175  	return param.GetFieldValue(IsAll) == True
   176  }
   177  
   178  func (param *Parameters) WithURLPath(path string) Parameters {
   179  	param.URLPath = path
   180  	return *param
   181  }
   182  
   183  func (param *Parameters) isAllTrue() {
   184  	param.Fields[IsAll] = []string{True}
   185  }
   186  
   187  func (param *Parameters) isAllFalse() {
   188  	param.Fields[IsAll] = []string{False}
   189  }
   190  
   191  func (param Parameters) WithIsAll(isAll bool) Parameters {
   192  	if isAll {
   193  		param.isAllTrue()
   194  	} else {
   195  		param.isAllFalse()
   196  	}
   197  	return param
   198  }
   199  
   200  func (param Parameters) DeleteIsAll() Parameters {
   201  	delete(param.Fields, IsAll)
   202  	return param
   203  }
   204  
   205  func (param Parameters) GetFilterFieldValueStart(field string) string {
   206  	return param.GetFieldValue(field + FilterRangeParamStartSuffix)
   207  }
   208  
   209  func (param Parameters) GetFilterFieldValueEnd(field string) string {
   210  	return param.GetFieldValue(field + FilterRangeParamEndSuffix)
   211  }
   212  
   213  func (param Parameters) GetFieldValue(field string) string {
   214  	value, ok := param.Fields[field]
   215  	if ok && len(value) > 0 {
   216  		return value[0]
   217  	}
   218  	return ""
   219  }
   220  
   221  func (param Parameters) AddField(field, value string) Parameters {
   222  	param.Fields[field] = []string{value}
   223  	return param
   224  }
   225  
   226  func (param Parameters) DeleteField(fields ...string) Parameters {
   227  	for _, field := range fields {
   228  		delete(param.Fields, field)
   229  	}
   230  	return param
   231  }
   232  
   233  func (param Parameters) DeleteEditPk() Parameters {
   234  	delete(param.Fields, constant.EditPKKey)
   235  	return param
   236  }
   237  
   238  func (param Parameters) DeleteDetailPk() Parameters {
   239  	delete(param.Fields, constant.DetailPKKey)
   240  	return param
   241  }
   242  
   243  func (param Parameters) GetFieldValues(field string) []string {
   244  	return param.Fields[field]
   245  }
   246  
   247  func (param Parameters) GetFieldValuesStr(field string) string {
   248  	return strings.Join(param.Fields[field], Separator)
   249  }
   250  
   251  func (param Parameters) GetFieldOperator(field, suffix string) string {
   252  	op := param.GetFieldValue(field + FilterParamOperatorSuffix + suffix)
   253  	if op == "" {
   254  		return "eq"
   255  	}
   256  	return op
   257  }
   258  
   259  func (param Parameters) Join() string {
   260  	p := param.GetFixedParamStr()
   261  	p.Add(Page, param.Page)
   262  	return p.Encode()
   263  }
   264  
   265  func (param *Parameters) SetPage(page string) Parameters {
   266  	param.Page = page
   267  	param.PageInt, _ = strconv.Atoi(page)
   268  	return *param
   269  }
   270  
   271  func (param *Parameters) SetPageSize(pageSize string) Parameters {
   272  	param.PageSize = pageSize
   273  	param.PageSizeInt, _ = strconv.Atoi(pageSize)
   274  	return *param
   275  }
   276  
   277  func (param Parameters) GetRouteParamStr() string {
   278  	p := param.GetFixedParamStr()
   279  	p.Add(Page, param.Page)
   280  	return "?" + p.Encode()
   281  }
   282  
   283  func (param Parameters) URL(page string) string {
   284  	return param.URLPath + param.SetPage(page).GetRouteParamStr()
   285  }
   286  
   287  func (param Parameters) URLNoAnimation(page string) string {
   288  	return param.URLPath + param.SetPage(page).GetRouteParamStr() + "&" + form.NoAnimationKey + "=true"
   289  }
   290  
   291  func (param Parameters) GetRouteParamStrWithoutPageSize(page string) string {
   292  	p := make(url.Values)
   293  	p.Add(Sort, param.SortField)
   294  	p.Add(Page, page)
   295  	p.Add(SortType, param.SortType)
   296  	if len(param.Columns) > 0 {
   297  		p.Add(Columns, strings.Join(param.Columns, ","))
   298  	}
   299  	for key, value := range param.Fields {
   300  		p[key] = value
   301  	}
   302  	return "?" + p.Encode()
   303  }
   304  
   305  func (param Parameters) GetFixedParamStrFromCache() url.Values {
   306  	if param.cacheFixedStr != nil {
   307  		return param.cacheFixedStr
   308  	}
   309  
   310  	p := param.GetFixedParamStr()
   311  	param.cacheFixedStr = p
   312  	return p
   313  }
   314  
   315  func (param Parameters) GetLastPageRouteParamStr(cache ...bool) string {
   316  	var p url.Values
   317  	if len(cache) > 0 && cache[0] {
   318  		p = param.GetFixedParamStrFromCache()
   319  	} else {
   320  		p = param.GetFixedParamStr()
   321  	}
   322  	p.Add(Page, strconv.Itoa(param.PageInt-1))
   323  	return "?" + p.Encode()
   324  }
   325  
   326  func (param Parameters) GetNextPageRouteParamStr(cache ...bool) string {
   327  	var p url.Values
   328  	if len(cache) > 0 && cache[0] {
   329  		p = param.GetFixedParamStrFromCache()
   330  	} else {
   331  		p = param.GetFixedParamStr()
   332  	}
   333  	p.Add(Page, strconv.Itoa(param.PageInt+1))
   334  	return "?" + p.Encode()
   335  }
   336  
   337  func (param Parameters) GetFixedParamStr() url.Values {
   338  	p := make(url.Values)
   339  	p.Add(Sort, param.SortField)
   340  	p.Add(PageSize, param.PageSize)
   341  	p.Add(SortType, param.SortType)
   342  	if len(param.Columns) > 0 {
   343  		p.Add(Columns, strings.Join(param.Columns, ","))
   344  	}
   345  	for key, value := range param.Fields {
   346  		p[key] = value
   347  	}
   348  	return p
   349  }
   350  
   351  func (param Parameters) GetFixedParamStrWithoutColumnsAndPage() string {
   352  	p := make(url.Values)
   353  	p.Add(Sort, param.SortField)
   354  	p.Add(PageSize, param.PageSize)
   355  	if len(param.Columns) > 0 {
   356  		p.Add(Columns, strings.Join(param.Columns, ","))
   357  	}
   358  	p.Add(SortType, param.SortType)
   359  	return "?" + p.Encode()
   360  }
   361  
   362  func (param Parameters) GetFixedParamStrWithoutSort() string {
   363  	p := make(url.Values)
   364  	p.Add(PageSize, param.PageSize)
   365  	for key, value := range param.Fields {
   366  		p[key] = value
   367  	}
   368  	p.Add(form.NoAnimationKey, "true")
   369  	if len(param.Columns) > 0 {
   370  		p.Add(Columns, strings.Join(param.Columns, ","))
   371  	}
   372  	return "&" + p.Encode()
   373  }
   374  
   375  func (param Parameters) Statement(wheres, table, delimiter, delimiter2 string, whereArgs []interface{}, columns, existKeys []string,
   376  	filterProcess func(string, string, string) string) (string, []interface{}, []string) {
   377  	var multiKey = make(map[string]uint8)
   378  	for key, value := range param.Fields {
   379  
   380  		keyIndexSuffix := ""
   381  
   382  		keyArr := strings.Split(key, FilterParamCountInfix)
   383  
   384  		if len(keyArr) > 1 {
   385  			key = keyArr[0]
   386  			keyIndexSuffix = FilterParamCountInfix + keyArr[1]
   387  		}
   388  
   389  		if keyIndexSuffix != "" {
   390  			multiKey[key] = 0
   391  		} else if _, exist := multiKey[key]; !exist && modules.InArray(existKeys, key) {
   392  			continue
   393  		}
   394  
   395  		var op string
   396  		if strings.Contains(key, FilterRangeParamEndSuffix) {
   397  			key = strings.ReplaceAll(key, FilterRangeParamEndSuffix, "")
   398  			op = "<="
   399  		} else if strings.Contains(key, FilterRangeParamStartSuffix) {
   400  			key = strings.ReplaceAll(key, FilterRangeParamStartSuffix, "")
   401  			op = ">="
   402  		} else if len(value) > 1 {
   403  			op = "in"
   404  		} else if !strings.Contains(key, FilterParamOperatorSuffix) {
   405  			op = operators[param.GetFieldOperator(key, keyIndexSuffix)]
   406  		} else {
   407  			continue
   408  		}
   409  
   410  		if strings.Contains(key, FilterParamJoinInfix) {
   411  			keys := strings.Split(key, FilterParamJoinInfix)
   412  			val := filterProcess(key, value[0], keyIndexSuffix)
   413  			if op == "in" {
   414  				qmark := ""
   415  				for range value {
   416  					qmark += "?,"
   417  				}
   418  				wheres += keys[0] + "." + modules.FilterField(keys[1], delimiter, delimiter2) + " " + op + " (" + qmark[:len(qmark)-1] + ") and "
   419  			} else {
   420  				wheres += keys[0] + "." + modules.FilterField(keys[1], delimiter, delimiter2) + " " + op + " ? and "
   421  			}
   422  			if op == "like" && !strings.Contains(val, "%") {
   423  				whereArgs = append(whereArgs, "%"+val+"%")
   424  			} else {
   425  				for _, v := range value {
   426  					whereArgs = append(whereArgs, filterProcess(key, v, keyIndexSuffix))
   427  				}
   428  			}
   429  		} else {
   430  			if modules.InArray(columns, key) {
   431  				if op == "in" {
   432  					qmark := ""
   433  					for range value {
   434  						qmark += "?,"
   435  					}
   436  					wheres += modules.Delimiter(delimiter, delimiter2, table) + "." + modules.FilterField(key, delimiter, delimiter2) + " " + op + " (" + qmark[:len(qmark)-1] + ") and "
   437  				} else {
   438  					wheres += modules.Delimiter(delimiter, delimiter2, table) + "." + modules.FilterField(key, delimiter, delimiter2) + " " + op + " ? and "
   439  				}
   440  				if op == "like" && !strings.Contains(value[0], "%") {
   441  					whereArgs = append(whereArgs, "%"+filterProcess(key, value[0], keyIndexSuffix)+"%")
   442  				} else {
   443  					for _, v := range value {
   444  						whereArgs = append(whereArgs, filterProcess(key, v, keyIndexSuffix))
   445  					}
   446  				}
   447  			} else {
   448  				continue
   449  			}
   450  		}
   451  
   452  		existKeys = append(existKeys, key)
   453  	}
   454  
   455  	if len(wheres) > 3 {
   456  		wheres = wheres[:len(wheres)-4]
   457  	}
   458  
   459  	for key, value := range param.OrConditions {
   460  		columns = strings.Split(key, ",")
   461  		op := "="
   462  		if strings.Contains(value, "%") {
   463  			op = "like"
   464  		}
   465  		if len(wheres) > 0 {
   466  			wheres += " and "
   467  		}
   468  		wheres += "("
   469  		for _, column := range columns {
   470  			keys := strings.Split(column, FilterParamJoinInfix)
   471  			if len(keys) > 1 {
   472  				wheres += keys[0] + "." + modules.FilterField(keys[1], delimiter, delimiter2) + " " + op + " ? or "
   473  			} else {
   474  				wheres += modules.FilterField(column, delimiter, delimiter2) + " " + op + " ? or "
   475  			}
   476  			whereArgs = append(whereArgs, value)
   477  		}
   478  		wheres = strings.TrimSuffix(wheres, "or ") + ")"
   479  	}
   480  
   481  	return wheres, whereArgs, existKeys
   482  }
   483  
   484  func getDefault(values url.Values, key, def string) string {
   485  	value := values.Get(key)
   486  	if value == "" {
   487  		return def
   488  	}
   489  	return value
   490  }