github.com/friesencr/pop/v6@v6.1.6/paginator.go (about) 1 package pop 2 3 import ( 4 "encoding/json" 5 "strconv" 6 7 "github.com/friesencr/pop/v6/internal/defaults" 8 ) 9 10 // PaginatorPerPageDefault is the amount of results per page 11 var PaginatorPerPageDefault = 20 12 13 // PaginatorPageKey is the query parameter holding the current page index 14 var PaginatorPageKey = "page" 15 16 // PaginatorPerPageKey is the query parameter holding the amount of results per page 17 // to override the default one 18 var PaginatorPerPageKey = "per_page" 19 20 type paginable interface { 21 Paginate() string 22 } 23 24 var _ paginable = Paginator{} 25 26 // Paginator is a type used to represent the pagination of records 27 // from the database. 28 type Paginator struct { 29 // Current page you're on 30 Page int `json:"page"` 31 // Number of results you want per page 32 PerPage int `json:"per_page"` 33 // Page * PerPage (ex: 2 * 20, Offset == 40) 34 Offset int `json:"offset"` 35 // Total potential records matching the query 36 TotalEntriesSize int `json:"total_entries_size"` 37 // Total records returns, will be <= PerPage 38 CurrentEntriesSize int `json:"current_entries_size"` 39 // Total pages 40 TotalPages int `json:"total_pages"` 41 } 42 43 // Paginate implements the paginable interface. 44 func (p Paginator) Paginate() string { 45 b, _ := json.Marshal(p) 46 return string(b) 47 } 48 49 func (p Paginator) String() string { 50 return p.Paginate() 51 } 52 53 // NewPaginator returns a new `Paginator` value with the appropriate 54 // defaults set. 55 func NewPaginator(page int, perPage int) *Paginator { 56 if page < 1 { 57 page = 1 58 } 59 if perPage < 1 { 60 perPage = 20 61 } 62 p := &Paginator{Page: page, PerPage: perPage} 63 p.Offset = (page - 1) * p.PerPage 64 return p 65 } 66 67 // PaginationParams is a parameters provider interface to get the pagination params from 68 type PaginationParams interface { 69 Get(key string) string 70 } 71 72 // NewPaginatorFromParams takes an interface of type `PaginationParams`, 73 // the `url.Values` type works great with this interface, and returns 74 // a new `Paginator` based on the params or `PaginatorPageKey` and 75 // `PaginatorPerPageKey`. Defaults are `1` for the page and 76 // PaginatorPerPageDefault for the per page value. 77 func NewPaginatorFromParams(params PaginationParams) *Paginator { 78 page := defaults.String(params.Get(PaginatorPageKey), "1") 79 80 perPage := defaults.String(params.Get(PaginatorPerPageKey), strconv.Itoa(PaginatorPerPageDefault)) 81 82 p, err := strconv.Atoi(page) 83 if err != nil { 84 p = 1 85 } 86 87 pp, err := strconv.Atoi(perPage) 88 if err != nil { 89 pp = PaginatorPerPageDefault 90 } 91 return NewPaginator(p, pp) 92 } 93 94 // Paginate records returned from the database. 95 // 96 // q := c.Paginate(2, 15) 97 // q.All(&[]User{}) 98 // q.Paginator 99 func (c *Connection) Paginate(page int, perPage int) *Query { 100 return Q(c).Paginate(page, perPage) 101 } 102 103 // Paginate records returned from the database. 104 // 105 // q = q.Paginate(2, 15) 106 // q.All(&[]User{}) 107 // q.Paginator 108 func (q *Query) Paginate(page int, perPage int) *Query { 109 q.Paginator = NewPaginator(page, perPage) 110 return q 111 } 112 113 // PaginateFromParams paginates records returned from the database. 114 // 115 // q := c.PaginateFromParams(req.URL.Query()) 116 // q.All(&[]User{}) 117 // q.Paginator 118 func (c *Connection) PaginateFromParams(params PaginationParams) *Query { 119 return Q(c).PaginateFromParams(params) 120 } 121 122 // PaginateFromParams paginates records returned from the database. 123 // 124 // q = q.PaginateFromParams(req.URL.Query()) 125 // q.All(&[]User{}) 126 // q.Paginator 127 func (q *Query) PaginateFromParams(params PaginationParams) *Query { 128 q.Paginator = NewPaginatorFromParams(params) 129 return q 130 }