Completed
Pull Request — master (#25)
by
unknown
04:49
created

Pagination::setPage()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.0534
c 0
b 0
f 0
cc 4
eloc 10
nc 3
nop 1
1
<?php
2
3
namespace Azine\EmailBundle\Services;
4
5
use Symfony\Component\HttpFoundation\Request;
6
use Symfony\Component\HttpFoundation\RequestStack;
7
8
class Pagination
9
{
10
    /**
11
     * @var int|null Current page number.
12
     */
13
    protected $currentPage;
14
15
    /**
16
     * @var string Name of query parameter that contains page number.
17
     */
18
    protected $pageParam = 'page';
19
20
    /**
21
     * @var string Name of query parameter that contains number of items on page.
22
     */
23
    protected $pageSizeParam = 'per-page';
24
25
    /**
26
     * @var string Name of route. If route was not specified then current route
27
     * will be used.
28
     */
29
    protected $route;
30
31
    /**
32
     * @var int Total number of items.
33
     */
34
    protected $totalCount = 0;
35
36
    /**
37
     * @var int Default number of items per page. Will be used if [[$pageSize]]
38
     * not specified.
39
     */
40
    protected $defaultPageSize = 20;
41
42
    /**
43
     * @var int Default limit of items per page.
44
     */
45
    protected $maxPageSize = 50;
46
47
    /**
48
     * @var int|null Default number of items per page.
49
     */
50
    protected $pageSize;
51
52
    /**
53
     * @var Request
54
     */
55
    protected $request;
56
57
    /**
58
     * Pagination constructor.
59
     *
60
     * @param RequestStack $requestStack
61
     */
62
    public function __construct(RequestStack $requestStack)
63
    {
64
        $this->request = $requestStack->getCurrentRequest();
65
    }
66
67
    /**
68
     * Calculate total number of pages.
69
     *
70
     * @return int number of pages
71
     */
72
    public function getPageCount()
73
    {
74
        $pageSize = $this->getPageSize();
75
76
        if ($pageSize < 1) {
77
            return $this->totalCount > 0 ? 1 : 0;
78
        }
79
80
        $totalCount = $this->totalCount < 0 ? 0 : (int)$this->totalCount;
81
82
        return (int)(($totalCount + $pageSize - 1) / $pageSize);
83
    }
84
85
    /**
86
     * Get current page number. Pages numeration starts from zero.
87
     *
88
     * @return int the zero-based current page number.
89
     */
90
    public function getCurrentPage()
91
    {
92
        if ($this->currentPage === null) {
93
            $currentPage = (int)$this->request->get($this->pageParam, 1) - 1;
94
95
            $this->setPage($currentPage);
96
        }
97
98
        return $this->currentPage;
99
    }
100
101
    /**
102
     * Set current page number.
103
     *
104
     * @param int $pageNumber
105
     *
106
     * @return $this
107
     */
108
    protected function setPage($pageNumber)
109
    {
110
        if (!is_numeric($pageNumber) || (int)$pageNumber <= 0) {
111
112
            $this->currentPage = 0;
113
114
            return $this;
115
        }
116
117
        $pageNumber = (int)$pageNumber;
118
119
        $totalPageCount = $this->getPageCount();
120
121
        if ($pageNumber >= $totalPageCount) {
122
            $pageNumber = $totalPageCount - 1;
123
        }
124
125
        $this->currentPage = $pageNumber;
126
127
        return $this;
128
    }
129
130
    /**
131
     * Get current number of items per page. If it's not specified yet the value
132
     * will be taken from query parameters. In other case default value will
133
     * be used.
134
     *
135
     * @return int
136
     */
137
    public function getPageSize()
138
    {
139
        if ($this->pageSize !== null) {
140
            return $this->pageSize;
141
        }
142
143
        $pageSize = (int)$this->request->get(
144
            $this->pageSizeParam,
145
            $this->defaultPageSize
146
        );
147
148
        $this->setPageSize($pageSize, true);
149
150
        return $this->pageSize;
151
    }
152
153
    /**
154
     * Set number of items to show per page. By default limit will be used.
155
     *
156
     * @param int $pageSize
157
     * @param bool $useLimit
158
     *
159
     * @return $this
160
     * @throws \Exception
161
     */
162
    public function setPageSize($pageSize, $useLimit = true)
163
    {
164
        if (!is_numeric($pageSize)) {
165
            throw new \Exception(
166
                'The expected type of the '.Pagination::class
167
                .' page size is a numeric.'.gettype($pageSize).' given.'
168
            );
169
        }
170
171
        $pageSize = (int)$pageSize;
172
173
        if ($useLimit && $pageSize > $this->maxPageSize) {
174
            $pageSize = $this->maxPageSize;
175
        } elseif ($pageSize < 0) {
176
            $pageSize = 0;
177
        }
178
179
        $this->pageSize = $pageSize;
180
181
        return $this;
182
    }
183
184
    /**
185
     * Fetch current route name.
186
     *
187
     * @return string
188
     */
189
    public function getRoute()
190
    {
191
        if (!$this->route) {
192
            $this->setRoute($this->request->attributes->all()['_route']);
193
        }
194
195
        return $this->route;
196
    }
197
198
    /**
199
     * @return int Get offset value that can be used in data source query.
200
     */
201
    public function getOffset()
202
    {
203
        $pageSize = $this->getPageSize();
204
205
        return $pageSize < 1 ? 0 : $this->getCurrentPage() * $pageSize;
206
    }
207
208
    /**
209
     * @return int Get limit value that can be used in data source query.]
210
     */
211
    public function getLimit()
212
    {
213
        $pageSize = $this->getPageSize();
214
215
        return $pageSize < 1 ? -1 : $pageSize;
216
    }
217
218
    /**
219
     * Get name of query parameter that stores current page index.
220
     *
221
     * @return string
222
     */
223
    public function getPageParamName()
224
    {
225
        return $this->pageParam;
226
    }
227
228
    /**
229
     * Get default number of items per page.
230
     *
231
     * @return int
232
     */
233
    public function getDefaultPageSize()
234
    {
235
        return $this->defaultPageSize;
236
    }
237
238
    /**
239
     * Get name of query parameter that stores number of items per page.
240
     *
241
     * @return string
242
     */
243
    public function getPageSizeParam()
244
    {
245
        return $this->pageSizeParam;
246
    }
247
248
    /**
249
     * Set total number of items.
250
     *
251
     * @param int $totalCount
252
     *
253
     * @return $this
254
     * @throws \Exception
255
     */
256 View Code Duplication
    public function setTotalCount($totalCount)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257
    {
258
        if (!is_numeric($totalCount)) {
259
            throw new \Exception(
260
                'The expected type of the '.Pagination::class
261
                .' items total count is a numeric.'.gettype($totalCount)
262
                .' given.'
263
            );
264
        }
265
266
        $this->totalCount = (int)$totalCount;
267
268
        return $this;
269
    }
270
271
    /**
272
     * Set route name.
273
     *
274
     * @param string $route Route name.
275
     *
276
     * @return $this
277
     * @throws \Exception
278
     */
279 View Code Duplication
    public function setRoute($route)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
280
    {
281
        if (!is_string($route)) {
282
            throw new \Exception(
283
                'The expected type of the '.Pagination::class
284
                .' route is a string. '.gettype($route).' given.'
285
            );
286
        }
287
288
        $this->route = $route;
289
290
        return $this;
291
    }
292
293
    /**
294
     * @param int $defaultPageSize
295
     *
296
     * @return $this
297
     * @throws \Exception
298
     */
299 View Code Duplication
    public function setDefaultPageSize($defaultPageSize)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
300
    {
301
        if (!is_numeric($defaultPageSize)) {
302
            throw new \Exception(
303
                'The expected type of the '.Pagination::class
304
                .' default page size is a numeric.'.gettype($defaultPageSize)
305
                .' given.'
306
            );
307
        }
308
309
        $this->defaultPageSize = (int)$defaultPageSize;
310
311
        return $this;
312
    }
313
314
    /**
315
     * @param string $pageSizeParam
316
     *
317
     * @return $this
318
     * @throws \Exception
319
     */
320 View Code Duplication
    public function setPageSizeParam($pageSizeParam)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
    {
322
        if (!is_string($pageSizeParam)) {
323
            throw new \Exception(
324
                'The expected type of the '.Pagination::class
325
                .' page size param name is a string. '.gettype($pageSizeParam)
326
                .' given.'
327
            );
328
        }
329
330
        $this->pageSizeParam = $pageSizeParam;
331
332
        return $this;
333
    }
334
335
    /**
336
     * @param string $pageParam
337
     *
338
     * @return $this
339
     * @throws \Exception
340
     */
341 View Code Duplication
    public function setPageParam($pageParam)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
342
    {
343
        if (!is_string($pageParam)) {
344
            throw new \Exception(
345
                'The expected type of the '.Pagination::class
346
                .' page param name is a string. '.gettype($pageParam)
347
                .' given.'
348
            );
349
        }
350
351
        $this->pageParam = $pageParam;
352
353
        return $this;
354
    }
355
}