-
Notifications
You must be signed in to change notification settings - Fork 3
/
tome.go
133 lines (110 loc) · 3.03 KB
/
tome.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2019 Cyro Dubeux. License MIT.
// Package tome was designed to paginate simple RESTful APIs.
package tome
import (
"errors"
"math"
"strconv"
)
// Chapter handles pagination results.
type Chapter struct {
// The base URL for the endpoint.
// It is only necessary when using links.
// Will be omitted from JSON when links are set to false.
BaseURL string `json:"base_url,omitempty"`
// The next URL string.
// Will be omitted from JSON when links are set to false.
NextURL string `json:"next_url,omitempty"`
// The previous URL string.
// Will be omitted from JSON when links are set to false.
PreviousURL string `json:"prev_url,omitempty"`
// Whether to create links or not.
// Pagination without links is faster.
Links bool `json:"-"`
// The inicial offset position.
Offset int `json:"-"`
// The limit per page.
// If none is provided, the limit will be setted to 10.
Limit int `json:"per_page"`
// The new page number captured on the request params.
// Will be omitted from JSON, since there is no need for it.
NewPage int `json:"-"`
// The current page of the tome.
// If none is provided, the current page will be setted to 1.
CurrentPage int `json:"current_page"`
// The last page of the tome.
LastPage int `json:"last_page"`
// The total results, this usually comes from
// a database query.
TotalResults int `json:"total_results"`
}
// Paginate handles the pagination calculation.
func (c *Chapter) Paginate() error {
c.setDefaults()
if err := c.ceilLastPage(); err != nil {
return err
}
if err := c.doPaginate(); err != nil {
return err
}
if err := c.checkLinks(); err != nil {
return err
}
return nil
}
// Calculates the offset and the limit.
func (c *Chapter) doPaginate() error {
if c.NewPage == 0 {
return errors.New("NewPage value is missing")
}
if c.NewPage > c.CurrentPage {
c.CurrentPage = c.NewPage
c.Offset = (c.CurrentPage - 1) * c.Limit
}
return nil
}
// Ceils the last page and generates
// a integer number.
func (c *Chapter) ceilLastPage() error {
if c.TotalResults == 0 {
return errors.New("TotalResults value is missing")
}
c.LastPage = int(math.Ceil(float64(c.TotalResults) / float64(c.Limit)))
return nil
}
// Handles links validations.
func (c *Chapter) checkLinks() error {
if !c.Links && c.BaseURL != "" {
return errors.New("Links value is false, set to true")
}
if c.Links {
if err := c.createLinks(); err != nil {
return err
}
}
return nil
}
// Creates next and previous links using
// the given base URL.
func (c *Chapter) createLinks() error {
if c.BaseURL == "" {
return errors.New("BaseURL value is missing")
}
if c.CurrentPage < c.LastPage {
c.NextURL = c.BaseURL + "?page=" + strconv.Itoa(c.CurrentPage+1)
}
if c.LastPage > c.CurrentPage {
c.PreviousURL = c.BaseURL + "?page=" + strconv.Itoa(c.CurrentPage-1)
}
return nil
}
// Sets the defaults values for current page
// and limit if none of them were provided.
func (c *Chapter) setDefaults() {
if c.CurrentPage == 0 {
c.CurrentPage = 1
}
if c.Limit == 0 {
c.Limit = 10
}
}