Passed
Push — master ( d65d4c...d10580 )
by CRISTIANO
01:13
created

Navigator::lastPageLink()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 5
rs 10
1
<?php
2
3
namespace DesignCafe\Navigator;
4
5
/**
6
 * Class Navigator
7
 * @package DesignCafe\Navigator
8
 */
9
class Navigator
10
{
11
    /** @var int */
12
    private $page;
13
14
    /** @var int */
15
    private $pages;
16
17
    /** @var int */
18
    private $rows;
19
20
    /** @var int */
21
    private $limit;
22
23
    /** @var int */
24
    private $offset;
25
26
    /** @var int */
27
    private $range;
28
29
    /** @var string */
30
    private $link;
31
32
    /** @var string */
33
    private $title;
34
35
    /** @var string */
36
    private $class;
37
38
    /** @var string */
39
    private $hash;
40
41
    /** @var array */
42
    private $first;
43
44
    /** @var array */
45
    private $last;
46
47
    /** @var int */
48
    private $links;
49
50
    /** @var int */
51
    private $min;
52
53
    /** @var int */
54
    private $max;
55
56
    /** @var int */
57
    private $qt_nav;
58
59
    /** @var bool */
60
    private $total;
61
62
    /**
63
     * Navigator constructor.
64
     * @param string|null $link
65
     * @param string|null $title
66
     * @param array|null $first
67
     * @param array|null $last
68
     */
69
    public function __construct(string $link = null, string $title = null, array $first = null, array $last = null)
70
    {
71
        $this->link = ($link ?? "?page=");
72
        $this->title = ($title ?? "Página");
73
        $this->first = ($first ?? ["Primeira página", "<<"]);
74
        $this->last = ($last ?? ["Última página", ">>"]);
75
    }
76
77
    /**
78
     * @param int $rows
79
     * @param int $limit
80
     * @param int|null $page
81
     * @param int $links
82
     * @param bool $total
83
     * @param string|null $hash
84
     */
85
    public function pager(int $rows, int $limit = 10, int $page = null, int $links = 7, string $hash = null
86
    ): void
87
    {
88
        $this->rows = $this->toPositive($rows);
89
        $this->limit = $this->toPositive($limit);
90
        $this->pages = (int)ceil($this->rows / $this->limit);
91
        $this->links = $this->pages < $links ? $this->pages : $links;
92
        $this->hash = (!empty($hash) ? "#{$hash}" : null);
93
        $this->page = ($page <= $this->pages ? $this->toPositive($page) : $this->pages);
94
95
        $this->range();
96
97
        $this->qtNav();
98
99
        $this->checkOffset();
100
    }
101
102
    /**
103
     * @return int
104
     */
105
    public function limit(): int
106
    {
107
        return $this->limit;
108
    }
109
110
    /**
111
     * @return int
112
     */
113
    public function offset(): int
114
    {
115
        return $this->offset;
116
    }
117
118
    /**
119
     * @return int
120
     */
121
    public function page(): int
122
    {
123
        return $this->page;
124
    }
125
126
    /**
127
     * @return int
128
     */
129
    public function pages(): int
130
    {
131
        return $this->pages;
132
    }
133
134
    /**
135
     * @param string $cssClass
136
     * @return null|string
137
     */
138
    public function render(string $cssClass = "navigator"): ?string
139
    {
140
        $this->class = $cssClass;
141
142
        if ($this->rows > $this->limit):
143
            $navigator = "<nav class=\"{$this->class}\">";
144
            $navigator .= $this->firstPageLink();
145
            $navigator .= $this->beforePages();
146
            $navigator .= "<span class=\"{$this->class}_item {$this->class}_active\">{$this->page}</span>";
147
            $navigator .= $this->afterPages();
148
            $navigator .= $this->lastPageLink();
149
            $navigator .= "</nav>";
150
            $navigator .= ($this->total && $this->links ? "<span>Página {$this->page} de {$this->pages}</span>" : '');
151
            return $navigator;
152
        endif;
153
154
        return null;
155
    }
156
157
    /**
158
     * @return string
159
     */
160
    private function firstPageLink(): string
161
    {
162
        return ($this->page == 1) ?
163
            "<a class='{$this->class}_item' title='{$this->first[0]}' href='#' onclick='return false;'>{$this->first[1]}</a>" :
164
            "<a class='{$this->class}_item' title='{$this->first[0]}' href='{$this->link}1{$this->hash}'>{$this->first[1]}</a>";
165
    }
166
167
    /**
168
     * @return string
169
     */
170
    private function lastPageLink(): string
171
    {
172
        return ($this->page == $this->pages) ?
173
            "<a class='{$this->class}_item' title='{$this->last[0]}' href='#' onclick='return false;'>{$this->last[1]}</a>" :
174
            "<a class='{$this->class}_item' title='{$this->last[0]}' href='{$this->link}{$this->pages}{$this->hash}'>{$this->last[1]}</a>";
175
    }
176
177
    /**
178
     * @return null|string
179
     */
180
    private function beforePages(): ?string
181
    {
182
        $before = null;
183
184
        if (($this->min > 1) && ($this->qt_nav < $this->links)) {
185
            $this->min = $this->min - ($this->links - $this->qt_nav);
186
        }
187
188
        for ($iPag = $this->min; $iPag <= $this->page - 1; $iPag++):
189
            if ($iPag >= 1):
190
                $before .= "<a class='{$this->class}_item' title=\"{$this->title} {$iPag}\" href=\"{$this->link}{$iPag}{$this->hash}\">{$iPag}</a>";
191
            endif;
192
        endfor;
193
194
        return $before;
195
    }
196
197
    /**
198
     * @return string|null
199
     */
200
    private function afterPages(): ?string
201
    {
202
        $after = null;
203
204
        if (($this->max < $this->pages) && ($this->qt_nav < $this->links)) {
205
            $this->max = $this->max + ($this->links - $this->qt_nav);
206
        }
207
208
        for ($dPag = $this->page + 1; $dPag <= $this->max; $dPag++):
209
            if ($dPag <= $this->pages):
210
                $after .= "<a class='{$this->class}_item' title=\"{$this->title} {$dPag}\" href=\"{$this->link}{$dPag}{$this->hash}\">{$dPag}</a>";
211
            endif;
212
        endfor;
213
214
        return $after;
215
    }
216
217
    /**
218
     * Calculate the range of pages
219
     */
220
    private function range(): void
221
    {
222
        if ($this->isEven($this->links)) {
223
            $this->links = $this->toPositive($this->links + 1);
224
            $this->range = $this->toPositive($this->links / 2);
225
        } else {
226
            $this->range = ($this->toPositive(($this->links - 1) / 2));
227
        }
228
    }
229
230
    /**
231
     * Define the Navigation Links quantity
232
     */
233
    private function qtNav(): void
234
    {
235
        $this->min = $this->toPositive($this->page - $this->range);
236
        $this->max = ($this->page + $this->range) > $this->pages ? $this->pages : $this->page + $this->range;
237
        $this->qt_nav = $this->max - $this->min + 1;
238
    }
239
240
    /**
241
     * Prevent the offset overbook
242
     */
243
    private function checkOffset(): void
244
    {
245
        $this->offset = (($this->page * $this->limit) - $this->limit >= 0 ? ($this->page * $this->limit) - $this->limit : 0);
246
247
        if ($this->rows && $this->offset >= $this->rows) {
248
            header("Location: {$this->link}" . ceil($this->rows / $this->limit));
249
            return;
250
        }
251
    }
252
253
    /**
254
     * @param $number
255
     * @return int
256
     */
257
    private function toPositive($number): int
258
    {
259
        return ($number >= 1 ? $number : 1);
260
    }
261
262
    /**
263
     * @param $number
264
     * @return bool
265
     */
266
    private function isEven($number): bool
267
    {
268
        return ($number % 2) ? false : true;
269
    }
270
}