Passed
Push — master ( d42e46...f4916d )
by compolom
01:38
created

Pagination   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Test Coverage

Coverage 75.82%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 92
c 3
b 0
f 0
dl 0
loc 219
ccs 69
cts 91
cp 0.7582
rs 8.4
wmc 50

12 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 19 6
A __construct() 0 9 5
A getCurrent() 0 20 6
A getOffset() 0 3 2
A getTotalPages() 0 3 1
B rightPad() 0 23 7
A start() 0 17 6
A get() 0 3 1
A end() 0 17 6
B leftPad() 0 24 7
A getLimit() 0 3 1
A getEnd() 0 3 2

How to fix   Complexity   

Complex Class

Complex classes like Pagination often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Pagination, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Compolomus\Pagination;
6
7
class Pagination
8
{
9
    private int $total;
10
11
    private int $page;
12
13
    private int $limit;
14
15
    private int $totalPages;
16
17
    private int $length;
18
19
    private string $pos;
20
21
    private bool $uiKeys;
22
23
    /**
24
     * @param int $page
25
     * @param int $limit
26
     * @param int $total
27
     * @param int $length
28
     * @param bool $uiKeys
29
     */
30 5
    public function __construct(int $page, int $limit, int $total, int $length = 3, bool $uiKeys = false)
31
    {
32 5
        $this->totalPages = (int) ceil($total / $limit);
33 5
        $this->page = $page > 1 ? ($page > $this->totalPages ? 1 : $page) : 1;
34 5
        $this->limit = $limit > 0 ? $limit : 10;
35 5
        $this->total = $total;
36 5
        $this->length = $length >= 0 ? $length : 3;
37 5
        $this->pos = $this->init();
38 5
        $this->uiKeys = $uiKeys;
39
    }
40
41 5
    private function init(): string
42
    {
43 5
        switch ($this->page) {
44 5
            case ($this->totalPages < 7):
45
            default:
46 4
                $pos = 'full';
47 4
                break;
48 1
            case (($this->page - $this->length) < 3):
49 1
                $pos = 'noLeftDots';
50 1
                break;
51 1
            case (($this->page - $this->length) >= 3 && ($this->totalPages - $this->page - $this->length) > 1):
52 1
                $pos = 'center';
53 1
                break;
54 1
            case (abs($this->totalPages - $this->page - $this->length) >= 0):
55 1
                $pos = 'noRightDots';
56 1
                break;
57
        }
58
59 5
        return $pos;
60
    }
61
62
    /**
63
     * @return int
64
     */
65 1
    public function getLimit(): int
66
    {
67 1
        return $this->limit;
68
    }
69
70
    /**
71
     * @return int
72
     */
73 1
    public function getEnd(): int
74
    {
75 1
        return $this->page === $this->totalPages ? $this->total : $this->page * $this->limit;
76
    }
77
78
    /**
79
     * @return int
80
     */
81 1
    public function getOffset(): int
82
    {
83 1
        return $this->page === 1 ? 0 : ($this->page - 1) * $this->limit;
84
    }
85
86
    /**
87
     * @return array
88
     */
89 1
    private function start(): array
90
    {
91 1
        $result = [];
92
93 1
        if ($this->uiKeys) {
94
            if ($this->page > 1) {
95
                $result['prev'] = $this->page - 1;
96
            }
97
            if ($this->page !== 1) {
98
                $result['first'] = 1;
99
            }
100
            if ($this->page > 3) {
101
                $result['second'] = 2;
102
            }
103
        }
104
105 1
        return $this->pos !== 'full' ? $result : [];
106
    }
107
108
    /**
109
     * @return array
110
     */
111 1
    private function end(): array
112
    {
113 1
        $result = [];
114
115 1
        if ($this->uiKeys) {
116
            if ($this->page !== $this->totalPages) {
117
                $result['last'] = $this->totalPages;
118
            }
119
            if ($this->totalPages - $this->page > 0) {
120
                $result['next'] = $this->page + 1;
121
            }
122
            if ($this->totalPages - $this->page + $this->length > 3) {
123
                $result['preLast'] = $this->totalPages - 1;
124
            }
125
        }
126
127 1
        return $this->pos !== 'full' ? $result : [];
128
    }
129
130
    /**
131
     * @return array
132
     */
133 1
    private function leftPad(): array
134
    {
135 1
        $result = [];
136 1
        $for = [];
137
138 1
        if ($this->pos !== 'full') {
139 1
            if ($this->page - $this->length > 1) {
140 1
                $result[] = 1;
141
            }
142 1
            if ($this->pos !== 'noLeftDots') {
143 1
                if ($this->uiKeys) {
144
                    $result['leftDots'] = '...';
145
                } else {
146 1
                    $result[] = '...';
147
                }
148
            }
149 1
            foreach (range($this->page - 1, $this->page - $this->length) as $value) {
150 1
                if ($value > 0) {
151 1
                    $for[] = $value;
152
                }
153
            }
154
        }
155
156 1
        return array_merge($result, array_reverse($for));
157
    }
158
159
    /**
160
     * @return array
161
     */
162 1
    private function rightPad(): array
163
    {
164 1
        $result = [];
165
166 1
        if ($this->pos !== 'full') {
167 1
            foreach (range($this->page + 1, $this->page + $this->length) as $value) {
168 1
                if ($value <= $this->totalPages) {
169 1
                    $result[] = $value;
170
                }
171
            }
172 1
            if ($this->pos !== 'noRightDots') {
173 1
                if ($this->uiKeys) {
174
                    $result['rightDots'] = '...';
175
                } else {
176 1
                    $result[] = '...';
177
                }
178
            }
179 1
            if ($this->totalPages - $this->page - $this->length > 0) {
180 1
                $result[] = $this->totalPages;
181
            }
182
        }
183
184 1
        return $result;
185
    }
186
187
    /**
188
     * @return array
189
     */
190 1
    private function getCurrent(): array
191
    {
192 1
        if ($this->uiKeys) {
193
            $result['current'] = $this->page;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.
Loading history...
194
        } else {
195 1
            $result[] = $this->page;
196
        }
197
198 1
        if ($this->pos === 'full') {
199
            $result = [];
200
            foreach (range(1, $this->totalPages) as $value) {
201
                if ($this->uiKeys && $value === $this->page) {
202
                    $result['current'] = $value;
203
                } else {
204
                    $result[] = $value;
205
                }
206
            }
207
        }
208
209 1
        return $result;
210
    }
211
212
    /**
213
     * @return array
214
     */
215 1
    public function get(): array
216
    {
217 1
        return array_merge($this->start(), $this->leftPad(), $this->getCurrent(), $this->rightPad(), $this->end());
218
    }
219
220
    /**
221
     * @return int
222
     */
223
    public function getTotalPages(): int
224
    {
225
        return $this->totalPages;
226
    }
227
}
228