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 }