2018-02-23 23:02:44 +08:00
|
|
|
// This package parse a http request from datatables (jQuery plugin) to a friendly structure
|
|
|
|
// More details in https://github.com/saulortega/datatables
|
|
|
|
// import "github.com/saulortega/datatables"
|
|
|
|
|
|
|
|
package datatables
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"net/http"
|
|
|
|
"regexp"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Column struct {
|
|
|
|
Data string
|
|
|
|
Name string
|
|
|
|
Index int
|
|
|
|
Orderable bool
|
|
|
|
Searchable bool
|
|
|
|
SearchValue string
|
|
|
|
SearchRegex bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type Order struct {
|
|
|
|
Column Column
|
|
|
|
Dir string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Filter struct {
|
|
|
|
Draw int
|
|
|
|
Start int
|
|
|
|
Length int
|
|
|
|
Order []Order
|
|
|
|
Columns []Column
|
|
|
|
SearchValue string
|
|
|
|
SearchRegex bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func Parse(r *http.Request) (Filter, error) {
|
|
|
|
return parse(r)
|
|
|
|
}
|
|
|
|
|
|
|
|
func MustParse(r *http.Request) Filter {
|
|
|
|
f, err := parse(r)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
2018-03-02 03:45:09 +08:00
|
|
|
func (f *Filter) PrepareResponse() Response {
|
|
|
|
return Response{Draw: f.Draw}
|
|
|
|
}
|
|
|
|
|
2018-02-23 23:02:44 +08:00
|
|
|
func parse(r *http.Request) (Filter, error) {
|
|
|
|
var E error
|
|
|
|
var F = Filter{
|
|
|
|
Order: []Order{},
|
|
|
|
Columns: []Column{},
|
|
|
|
}
|
|
|
|
|
|
|
|
var errores = []string{}
|
|
|
|
var mapColsTmp = make(map[int]map[string]string)
|
|
|
|
var mapOrdsTmp = make(map[int]map[string]string)
|
|
|
|
|
2018-03-02 03:45:09 +08:00
|
|
|
F.Draw, E = ptoi(r, "draw")
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
F.Start, E = ptoi(r, "start")
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
F.Length, E = ptoi(r, "length")
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
F.SearchValue, E = ptos(r, "search[value]")
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
F.SearchRegex, E = ptob(r, "search[regex]")
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
|
2018-02-23 23:02:44 +08:00
|
|
|
for ll, v := range r.Form {
|
|
|
|
if regexp.MustCompile(`^columns\[`).MatchString(ll) {
|
|
|
|
a := regexp.MustCompile(`^columns\[([0-9]+)\]\[`).ReplaceAllString(ll, "$1-")
|
|
|
|
a = regexp.MustCompile(`search\]\[(value|regex)`).ReplaceAllString(a, "search$1")
|
|
|
|
a = regexp.MustCompile(`\]$`).ReplaceAllString(a, "")
|
|
|
|
p := strings.Split(a, "-")
|
|
|
|
i, er := strconv.Atoi(p[0])
|
|
|
|
if er != nil {
|
|
|
|
errores = append(errores, er.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := mapColsTmp[i]; !ok {
|
|
|
|
mapColsTmp[i] = make(map[string]string)
|
|
|
|
}
|
|
|
|
mapColsTmp[i][p[1]] = v[0]
|
|
|
|
} else if regexp.MustCompile(`^order\[`).MatchString(ll) {
|
|
|
|
a := regexp.MustCompile(`^order\[([0-9]+)\]\[`).ReplaceAllString(ll, "$1-")
|
|
|
|
a = regexp.MustCompile(`\]$`).ReplaceAllString(a, "")
|
|
|
|
p := strings.Split(a, "-")
|
|
|
|
i, er := strconv.Atoi(p[0])
|
|
|
|
if er != nil {
|
|
|
|
errores = append(errores, er.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := mapOrdsTmp[i]; !ok {
|
|
|
|
mapOrdsTmp[i] = make(map[string]string)
|
|
|
|
}
|
|
|
|
mapOrdsTmp[i][p[1]] = v[0]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(mapColsTmp); i++ {
|
|
|
|
c := Column{Index: i}
|
|
|
|
c.Data = strings.TrimSpace(mapColsTmp[i]["data"])
|
|
|
|
c.Name = strings.TrimSpace(mapColsTmp[i]["name"])
|
|
|
|
c.Orderable, E = strconv.ParseBool(mapColsTmp[i]["orderable"])
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
c.Searchable, E = strconv.ParseBool(mapColsTmp[i]["searchable"])
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
c.SearchValue = strings.TrimSpace(mapColsTmp[i]["searchvalue"])
|
|
|
|
c.SearchRegex, E = strconv.ParseBool(mapColsTmp[i]["searchregex"])
|
|
|
|
if E != nil {
|
|
|
|
errores = append(errores, E.Error())
|
|
|
|
}
|
|
|
|
F.Columns = append(F.Columns, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(mapOrdsTmp); i++ {
|
|
|
|
dir := strings.ToUpper(mapOrdsTmp[i]["dir"])
|
|
|
|
ic, er := strconv.Atoi(mapOrdsTmp[i]["column"])
|
|
|
|
if er != nil || (dir != "ASC" && dir != "DESC") {
|
|
|
|
if er != nil {
|
|
|
|
errores = append(errores, er.Error())
|
|
|
|
} else {
|
|
|
|
errores = append(errores, "dir invalid: «"+dir+"»")
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
o := Order{Dir: dir}
|
|
|
|
for _, c := range F.Columns {
|
2018-02-24 03:50:27 +08:00
|
|
|
if c.Index == ic && c.Orderable {
|
2018-02-23 23:02:44 +08:00
|
|
|
o.Column = c
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if o.Column == (Column{}) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
F.Order = append(F.Order, o)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(errores) > 0 {
|
|
|
|
E = errors.New(strings.Join(errores, "; "))
|
|
|
|
}
|
|
|
|
|
|
|
|
return F, E
|
|
|
|
}
|