Paginator   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 226
Duplicated Lines 0 %

Importance

Changes 17
Bugs 0 Features 0
Metric Value
wmc 30
eloc 73
c 17
b 0
f 0
dl 0
loc 226
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A toPositive() 0 3 2
A firstPage() 0 6 3
A pager() 0 22 6
A afterPages() 0 10 3
A beforePages() 0 10 3
A addGetParams() 0 14 3
A lastPage() 0 6 3
A pages() 0 3 1
A offset() 0 3 1
A limit() 0 3 1
A render() 0 16 2
A page() 0 3 1
1
<?php
2
3
namespace CoffeeCode\Paginator;
4
5
/**
6
 * Class CoffeeCode Paginator
7
 *
8
 * @author Robson V. Leite <https://github.com/robsonvleite>
9
 * @package CoffeeCode\Paginator
10
 */
11
class Paginator
12
{
13
    /** @var int|null */
14
    private ?int $page;
15
16
    /** @var int */
17
    private int $pages;
18
19
    /** @var int */
20
    private int $rows;
21
22
    /** @var int|null */
23
    private ?int $limit;
24
25
    /** @var int|null */
26
    private ?int $offset;
27
28
    /** @var int */
29
    private int $range;
30
31
    /** @var string */
32
    private ?string $link;
33
34
    /** @var string */
35
    private string $title;
36
37
    /** @var string */
38
    private string $class;
39
40
    /** @var string|null */
41
    private ?string $hash;
42
43
    /** @var array */
44
    private array $first;
45
46
    /** @var array */
47
    private array $last;
48
49
    /** @var string */
50
    private string $params;
51
52
    /**
53
     * Paginator constructor.
54
     * @param string|null $link
55
     * @param string|null $title
56
     * @param array|null $first
57
     * @param array|null $last
58
     */
59
    public function __construct(string $link = null, string $title = null, array $first = null, array $last = null)
60
    {
61
        $this->link = ($link ?? "?page=");
62
        $this->title = ($title ?? "Página");
63
        $this->first = ($first ?? ["Primeira página", "<<"]);
64
        $this->last = ($last ?? ["Última página", ">>"]);
65
    }
66
67
    /**
68
     * @param int $rows
69
     * @param int $limit
70
     * @param int|null $page
71
     * @param int $range
72
     * @param string|null $hash
73
     * @param array $params
74
     */
75
    public function pager(
76
        int $rows,
77
        int $limit = 10,
78
        int $page = null,
79
        int $range = 3,
80
        string $hash = null,
81
        array $params = []
82
    ): void {
83
        $this->rows = $this->toPositive($rows);
84
        $this->limit = $this->toPositive($limit);
85
        $this->range = $this->toPositive($range);
86
        $this->pages = (int)ceil($this->rows / $this->limit);
87
        $this->page = ($page <= $this->pages ? $this->toPositive($page) : $this->pages);
88
89
        $this->offset = (($this->page * $this->limit) - $this->limit >= 0 ? ($this->page * $this->limit) - $this->limit : 0);
90
        $this->hash = (!empty($hash) ? "#{$hash}" : null);
91
92
        $this->addGetParams($params);
93
94
        if ($this->rows && $this->offset >= $this->rows) {
95
            header("Location: {$this->link}" . ceil($this->rows / $this->limit));
96
            exit;
97
        }
98
    }
99
100
    /**
101
     * @return int
102
     */
103
    public function limit(): ?int
104
    {
105
        return $this->limit;
106
    }
107
108
    /**
109
     * @return int
110
     */
111
    public function offset(): ?int
112
    {
113
        return $this->offset;
114
    }
115
116
    /**
117
     * @return int
118
     */
119
    public function page(): ?int
120
    {
121
        return $this->page;
122
    }
123
124
    /**
125
     * @return int
126
     */
127
    public function pages(): int
128
    {
129
        return $this->pages;
130
    }
131
132
    /**
133
     * @param string|null $cssClass
134
     * @param bool $fixedFirstAndLastPage
135
     * @return null|string
136
     */
137
    public function render(string $cssClass = null, bool $fixedFirstAndLastPage = true): ?string
138
    {
139
        $this->class = $cssClass ?? "paginator";
140
141
        if ($this->rows > $this->limit):
142
            $paginator = "<nav class=\"{$this->class}\">";
143
            $paginator .= $this->firstPage($fixedFirstAndLastPage);
144
            $paginator .= $this->beforePages();
145
            $paginator .= "<span class=\"{$this->class}_item {$this->class}_active\">{$this->page}</span>";
146
            $paginator .= $this->afterPages();
147
            $paginator .= $this->lastPage($fixedFirstAndLastPage);
148
            $paginator .= "</nav>";
149
            return $paginator;
150
        endif;
151
152
        return null;
153
    }
154
155
    /**
156
     * @return null|string
157
     */
158
    private function beforePages(): ?string
159
    {
160
        $before = null;
161
        for ($iPag = $this->page - $this->range; $iPag <= $this->page - 1; $iPag++):
162
            if ($iPag >= 1):
163
                $before .= "<a class=\"{$this->class}_item\" aria-label=\"{$this->title} {$iPag}\" title=\"{$this->title} {$iPag}\" href=\"{$this->link}{$iPag}{$this->hash}{$this->params}\">{$iPag}</a>";
164
            endif;
165
        endfor;
166
167
        return $before;
168
    }
169
170
    /**
171
     * @return string|null
172
     */
173
    private function afterPages(): ?string
174
    {
175
        $after = null;
176
        for ($dPag = $this->page + 1; $dPag <= $this->page + $this->range; $dPag++):
177
            if ($dPag <= $this->pages):
178
                $after .= "<a class=\"{$this->class}_item\" aria-label=\"{$this->title} {$dPag}\" title=\"{$this->title} {$dPag}\" href=\"{$this->link}{$dPag}{$this->hash}{$this->params}\">{$dPag}</a>";
179
            endif;
180
        endfor;
181
182
        return $after;
183
    }
184
185
    /**
186
     * @param bool $fixedFirstAndLastPage
187
     * @return string|null
188
     */
189
    public function firstPage(bool $fixedFirstAndLastPage = true): ?string
190
    {
191
        if ($fixedFirstAndLastPage || $this->page != 1) {
192
            return "<a class=\"{$this->class}_item\" aria-label=\"{$this->first[0]}\" title=\"{$this->first[0]}\" href=\"{$this->link}1{$this->hash}{$this->params}\">{$this->first[1]}</a>";
193
        }
194
        return null;
195
    }
196
197
    /**
198
     * @param bool $fixedFirstAndLastPage
199
     * @return string|null
200
     */
201
    public function lastPage(bool $fixedFirstAndLastPage = true): ?string
202
    {
203
        if ($fixedFirstAndLastPage || $this->page != $this->pages) {
204
            return "<a class=\"{$this->class}_item\" aria-label=\"{$this->last[0]}\" title=\"{$this->last[0]}\" href=\"{$this->link}{$this->pages}{$this->hash}{$this->params}\">{$this->last[1]}</a>";
205
        }
206
        return null;
207
    }
208
209
    /**
210
     * @param $number
211
     * @return int
212
     */
213
    private function toPositive($number): int
214
    {
215
        return ($number >= 1 ? $number : 1);
216
    }
217
218
    /**
219
     * Add get parameters
220
     * @param array $params
221
     * @return Paginator
222
     */
223
    private function addGetParams(array $params): Paginator
224
    {
225
        $this->params = '';
226
227
        if (count($params) > 0) {
228
            if (isset($params['page'])) {
229
                unset($params['page']);
230
            }
231
232
            $this->params = '&';
233
            $this->params .= http_build_query($params);
234
        }
235
236
        return $this;
237
    }
238
}