|
- // 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
- }
-
- func (f *Filter) PrepareResponse() Response {
- return Response{Draw: f.Draw}
- }
-
- 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)
-
- 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())
- }
-
- 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 {
- if c.Index == ic && c.Orderable {
- 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
- }
|