github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/api/util/order.go (about)

     1  package util
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"strings"
     8  )
     9  
    10  var (
    11  	// OrderASC defines the ascending order keyword
    12  	OrderASC = "asc"
    13  	// OrderDESC defines the descending order keyword
    14  	OrderDESC = "desc"
    15  )
    16  
    17  // OrderBy represents ordering information
    18  type OrderBy []Order
    19  
    20  // Order represents ordering information for a single key
    21  type Order struct {
    22  	Key       string
    23  	Direction string
    24  }
    25  
    26  // NewOrder constructs a basic order struct
    27  func NewOrder(key, orderDirection string) Order {
    28  	if orderDirection != OrderASC && orderDirection != OrderDESC {
    29  		orderDirection = OrderDESC
    30  	}
    31  	return Order{
    32  		Key:       key,
    33  		Direction: orderDirection,
    34  	}
    35  }
    36  
    37  // String implements the stringer interface for OrderBy
    38  func (o OrderBy) String() string {
    39  	var b strings.Builder
    40  	for i, oi := range o {
    41  		if i > 0 {
    42  			b.WriteString(",")
    43  		}
    44  		b.WriteString(oi.String())
    45  	}
    46  	return b.String()
    47  }
    48  
    49  // String implements the stringer interface for Order
    50  func (o Order) String() string {
    51  	return fmt.Sprintf("%s,%s", o.Key, o.Direction)
    52  }
    53  
    54  // SetQueryParams adds order by info to a url as query parameters
    55  func (o OrderBy) SetQueryParams(u *url.URL) *url.URL {
    56  	q := u.Query()
    57  	if len(o) > 0 {
    58  		q.Set("orderBy", o.String())
    59  	}
    60  
    61  	u.RawQuery = q.Encode()
    62  	return u
    63  }
    64  
    65  // OrderByFromRequest extracts orderBy params from an http request
    66  func OrderByFromRequest(r *http.Request) OrderBy {
    67  	orderBy := r.FormValue("orderBy")
    68  	return NewOrderByFromString(orderBy, nil)
    69  }
    70  
    71  // OrderByFromRequestWithKeys extracts orderBy params from an
    72  // http request and only takes the specified keys
    73  func OrderByFromRequestWithKeys(r *http.Request, validKeys []string) OrderBy {
    74  	orderBy := r.FormValue("orderBy")
    75  	return NewOrderByFromString(orderBy, validKeys)
    76  }
    77  
    78  // NewOrderByFromString converts a commaa delimited string to an OrderBy struct
    79  func NewOrderByFromString(orderBy string, validKeys []string) OrderBy {
    80  	orderComponents := strings.Split(orderBy, ",")
    81  	if orderBy == "" || len(orderComponents) == 0 || (len(orderComponents) != 1 && len(orderComponents)%2 == 1) {
    82  		return []Order{}
    83  	}
    84  	res := []Order{}
    85  	if len(orderComponents) == 1 {
    86  		res = append(res, NewOrder(strings.TrimSpace(orderComponents[0]), OrderDESC))
    87  		return res
    88  	}
    89  	for i := 0; i <= len(orderComponents)/2; i += 2 {
    90  		orderDirection := ""
    91  		if strings.ToLower(orderComponents[i+1]) == OrderASC {
    92  			orderDirection = OrderASC
    93  		} else {
    94  			orderDirection = OrderDESC
    95  		}
    96  		orderKey := strings.TrimSpace(orderComponents[i])
    97  		if validKeys != nil {
    98  			for _, vkey := range validKeys {
    99  				if vkey == orderKey {
   100  					res = append(res, NewOrder(orderKey, orderDirection))
   101  					break
   102  				}
   103  			}
   104  		} else {
   105  			res = append(res, NewOrder(orderKey, orderDirection))
   106  		}
   107  	}
   108  
   109  	return res
   110  }