You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
3.8 KiB

  1. // This package parse a http request from datatables (jQuery plugin) to a friendly structure
  2. // More details in https://github.com/saulortega/datatables
  3. // import "github.com/saulortega/datatables"
  4. package datatables
  5. import (
  6. "errors"
  7. "net/http"
  8. "regexp"
  9. "strconv"
  10. "strings"
  11. )
  12. type Column struct {
  13. Data string
  14. Name string
  15. Index int
  16. Orderable bool
  17. Searchable bool
  18. SearchValue string
  19. SearchRegex bool
  20. }
  21. type Order struct {
  22. Column Column
  23. Dir string
  24. }
  25. type Filter struct {
  26. Draw int
  27. Start int
  28. Length int
  29. Order []Order
  30. Columns []Column
  31. SearchValue string
  32. SearchRegex bool
  33. }
  34. func Parse(r *http.Request) (Filter, error) {
  35. return parse(r)
  36. }
  37. func MustParse(r *http.Request) Filter {
  38. f, err := parse(r)
  39. if err != nil {
  40. panic(err)
  41. }
  42. return f
  43. }
  44. func (f *Filter) PrepareResponse() Response {
  45. return Response{Draw: f.Draw}
  46. }
  47. func parse(r *http.Request) (Filter, error) {
  48. var E error
  49. var F = Filter{
  50. Order: []Order{},
  51. Columns: []Column{},
  52. }
  53. var errores = []string{}
  54. var mapColsTmp = make(map[int]map[string]string)
  55. var mapOrdsTmp = make(map[int]map[string]string)
  56. F.Draw, E = ptoi(r, "draw")
  57. if E != nil {
  58. errores = append(errores, E.Error())
  59. }
  60. F.Start, E = ptoi(r, "start")
  61. if E != nil {
  62. errores = append(errores, E.Error())
  63. }
  64. F.Length, E = ptoi(r, "length")
  65. if E != nil {
  66. errores = append(errores, E.Error())
  67. }
  68. F.SearchValue, E = ptos(r, "search[value]")
  69. if E != nil {
  70. errores = append(errores, E.Error())
  71. }
  72. F.SearchRegex, E = ptob(r, "search[regex]")
  73. if E != nil {
  74. errores = append(errores, E.Error())
  75. }
  76. for ll, v := range r.Form {
  77. if regexp.MustCompile(`^columns\[`).MatchString(ll) {
  78. a := regexp.MustCompile(`^columns\[([0-9]+)\]\[`).ReplaceAllString(ll, "$1-")
  79. a = regexp.MustCompile(`search\]\[(value|regex)`).ReplaceAllString(a, "search$1")
  80. a = regexp.MustCompile(`\]$`).ReplaceAllString(a, "")
  81. p := strings.Split(a, "-")
  82. i, er := strconv.Atoi(p[0])
  83. if er != nil {
  84. errores = append(errores, er.Error())
  85. continue
  86. }
  87. if _, ok := mapColsTmp[i]; !ok {
  88. mapColsTmp[i] = make(map[string]string)
  89. }
  90. mapColsTmp[i][p[1]] = v[0]
  91. } else if regexp.MustCompile(`^order\[`).MatchString(ll) {
  92. a := regexp.MustCompile(`^order\[([0-9]+)\]\[`).ReplaceAllString(ll, "$1-")
  93. a = regexp.MustCompile(`\]$`).ReplaceAllString(a, "")
  94. p := strings.Split(a, "-")
  95. i, er := strconv.Atoi(p[0])
  96. if er != nil {
  97. errores = append(errores, er.Error())
  98. continue
  99. }
  100. if _, ok := mapOrdsTmp[i]; !ok {
  101. mapOrdsTmp[i] = make(map[string]string)
  102. }
  103. mapOrdsTmp[i][p[1]] = v[0]
  104. }
  105. }
  106. for i := 0; i < len(mapColsTmp); i++ {
  107. c := Column{Index: i}
  108. c.Data = strings.TrimSpace(mapColsTmp[i]["data"])
  109. c.Name = strings.TrimSpace(mapColsTmp[i]["name"])
  110. c.Orderable, E = strconv.ParseBool(mapColsTmp[i]["orderable"])
  111. if E != nil {
  112. errores = append(errores, E.Error())
  113. }
  114. c.Searchable, E = strconv.ParseBool(mapColsTmp[i]["searchable"])
  115. if E != nil {
  116. errores = append(errores, E.Error())
  117. }
  118. c.SearchValue = strings.TrimSpace(mapColsTmp[i]["searchvalue"])
  119. c.SearchRegex, E = strconv.ParseBool(mapColsTmp[i]["searchregex"])
  120. if E != nil {
  121. errores = append(errores, E.Error())
  122. }
  123. F.Columns = append(F.Columns, c)
  124. }
  125. for i := 0; i < len(mapOrdsTmp); i++ {
  126. dir := strings.ToUpper(mapOrdsTmp[i]["dir"])
  127. ic, er := strconv.Atoi(mapOrdsTmp[i]["column"])
  128. if er != nil || (dir != "ASC" && dir != "DESC") {
  129. if er != nil {
  130. errores = append(errores, er.Error())
  131. } else {
  132. errores = append(errores, "dir invalid: «"+dir+"»")
  133. }
  134. continue
  135. }
  136. o := Order{Dir: dir}
  137. for _, c := range F.Columns {
  138. if c.Index == ic && c.Orderable {
  139. o.Column = c
  140. break
  141. }
  142. }
  143. if o.Column == (Column{}) {
  144. continue
  145. }
  146. F.Order = append(F.Order, o)
  147. }
  148. if len(errores) > 0 {
  149. E = errors.New(strings.Join(errores, "; "))
  150. }
  151. return F, E
  152. }