Pagination::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 1
Metric Value
cc 2
eloc 7
c 4
b 1
f 1
nc 2
nop 1
dl 0
loc 10
rs 10
1
<?php
2
    defined('ROOT_PATH') || exit('Access denied');
3
    /**
4
     * TNH Framework
5
     *
6
     * A simple PHP framework using HMVC architecture
7
     *
8
     * This content is released under the MIT License (MIT)
9
     *
10
     * Copyright (c) 2017 TNH Framework
11
     *
12
     * Permission is hereby granted, free of charge, to any person obtaining a copy
13
     * of this software and associated documentation files (the "Software"), to deal
14
     * in the Software without restriction, including without limitation the rights
15
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
     * copies of the Software, and to permit persons to whom the Software is
17
     * furnished to do so, subject to the following conditions:
18
     *
19
     * The above copyright notice and this permission notice shall be included in all
20
     * copies or substantial portions of the Software.
21
     *
22
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
     * SOFTWARE.
29
     */
30
31
    class Pagination {
32
        
33
        /**
34
         * The list of loaded config
35
         * @var array
36
         */
37
        private $config = array();
38
39
        /**
40
         * The pagination current query string
41
         * @var string
42
         */
43
        private $paginationQueryString = null;
44
45
        /**
46
         * Create an instance of pagination
47
         * @param array $overwriteConfig the list of configuration to overwrite the 
48
         * defined configuration in config_pagination.php
49
         */
50
        public function __construct(array $overwriteConfig = array()) {
51
            $config = array();
52
            if (file_exists(CONFIG_PATH . 'config_pagination.php')) {
53
                require CONFIG_PATH . 'config_pagination.php';
54
            } 
55
            $config = array_merge($config, $overwriteConfig);
56
            $this->config = $config;
57
            //put it gobally
58
            get_instance()->config->setAll($config);
59
            unset($config);
60
        }
61
62
63
        /**
64
         * Set the pagination custom configuration to overwrite the default configuration in
65
         * config_pagination.php
66
         * @param array $config the configuration to overwrite
67
         */
68
        public function setConfig(array $config = array()) {
69
            if (!empty($config)) {
70
                $this->config = array_merge($this->config, $config);
71
                get_instance()->config->setAll($config);
72
            }
73
        }
74
75
        /**
76
         * Return the value of the pagination configuration
77
         * 
78
         * @return array
79
         */
80
        public function getConfig() {
81
            return $this->config;
82
        }
83
84
        /**
85
         * Get pagination information
86
         * @param  int $totalRows the total number of data
87
         * @param  int $currentPageNumber the current page number
88
         * @return array
89
         */
90
        public function getInfos($totalRows, $currentPageNumber){
91
            $numberOfRowPerPage = (int)$this->config['pagination_per_page'];
92
            $numberOfPage = (int)ceil($totalRows / $numberOfRowPerPage);
93
            $numberOfLink = (int)$this->config['nb_link'];
94
            $infos['current_page'] = $currentPageNumber;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$infos was never initialized. Although not strictly required by PHP, it is generally a good practice to add $infos = array(); before regardless.
Loading history...
95
            $infos['num_links'] = $numberOfLink;
96
            $infos['limit'] = $numberOfRowPerPage;
97
            $infos['total_page'] = $numberOfPage;
98
            $infos['total_rows'] = $totalRows;
99
            $infos['is_first_page'] = $currentPageNumber == 1;
100
            $infos['is_last_page'] = $currentPageNumber == $numberOfPage;
101
            $infos['prev_page'] = ($numberOfPage > 1 && $currentPageNumber > 1) ? $currentPageNumber - 1 : $currentPageNumber;
102
            $infos['next_page'] = ($numberOfPage > 1 && $currentPageNumber < $numberOfPage) ? $currentPageNumber + 1 : $currentPageNumber;
103
            $infos['has_prev_page'] = $numberOfPage > 1 && $currentPageNumber > 1;
104
            $infos['has_next_page'] = $numberOfPage > 1 && $currentPageNumber < $numberOfPage;
105
            
106
            return $infos;
107
        }
108
109
        /**
110
         * Generate the pagination link
111
         * @param  int $totalRows the total number of data
112
         * @param  int $currentPageNumber the current page number
113
         * 
114
         * @return null|string the pagination link
115
         */
116
        public function getLink($totalRows, $currentPageNumber) {
117
            $infos = $this->getInfos($totalRows, $currentPageNumber);
118
            $numberOfRowPerPage = $infos['limit'];
119
            $numberOfPage = $infos['total_page'];
120
            
121
            //determine the pagination query string value
122
            $this->determinePaginationQueryStringValue();
123
            
124
            $currentPageNumber = (int)$currentPageNumber;
125
            
126
            if ($currentPageNumber <= 0) {
127
                $currentPageNumber = 1;
128
            }
129
            if ($numberOfPage <= 1 || $infos['num_links'] <= 0 || $numberOfRowPerPage <= 0) {
130
                return null;
131
            }
132
133
            return $this->buildPaginationNavbar($currentPageNumber, $numberOfPage);
134
        }
135
136
        /**
137
         * Determine automatically the value of the pagination query string
138
         * Using the REQUEST URI
139
         * 
140
         * @return object
141
         */
142
        protected function determinePaginationQueryStringValue() {
143
            $pageQueryName = $this->config['page_query_string_name'];
144
            $queryString = get_instance()->url->queryString();
145
            $currentUrl = get_instance()->url->current();
146
            $query = '';
147
            if ($queryString == '') {
148
                $query = '?' . $pageQueryName . '=';
149
            } else {
150
                $tab = explode($pageQueryName . '=', $queryString);
151
                $nb = count($tab);
152
                if ($nb == 1) {
153
                    $query = '?' . $queryString . '&' . $pageQueryName . '=';
154
                } else {
155
                    if ($tab[0] == '') {
156
                        $query = '?' . $pageQueryName . '=';
157
                    } else {
158
                        $query = '?' . $tab[0] . '' . $pageQueryName . '=';
159
                    }
160
                }
161
            }
162
            $temp = explode('?', $currentUrl);
163
            $query = $temp[0] . $query;
164
            $this->paginationQueryString = $query;
165
            return $this;
166
        }
167
168
        /**
169
         * Build the pagination navbar with the link numbers
170
         * @param  int $currentPageNumber the current page number
171
         * @param  int $numberOfPage      the total number of page
172
         * @return string
173
         */
174
        protected function buildPaginationNavbar($currentPageNumber, $numberOfPage) {
175
            $values = $this->getPaginationBeginAndEndNumber($currentPageNumber, $numberOfPage);
176
            $begin = $values['begin'];
177
            $end   = $values['end'];
178
            $navbar = null;
179
            if ($currentPageNumber == 1) {
180
                $navbar .= $this->buildPaginationLinkForFirstPage($begin, $end, $currentPageNumber);
181
            } else if ($currentPageNumber > 1 && $currentPageNumber < $numberOfPage) {
182
                $navbar .= $this->buildPaginationLinkForMiddlePage($begin, $end, $currentPageNumber);
183
            } else if ($currentPageNumber == $numberOfPage) {
184
                $navbar .= $this->buildPaginationLinkForLastPage($begin, $end, $currentPageNumber);
185
            }
186
            $navbar = $this->config['pagination_open'] . $navbar . $this->config['pagination_close'];
187
            return $navbar;
188
        }
189
190
        /**
191
         * Get the pagination begin and end link numbers
192
         * @param  int $currentPageNumber the current page number
193
         * @param  int $numberOfPage      the total number of page
194
         * @return array                    the begin and end number
195
         */
196
        protected function getPaginationBeginAndEndNumber($currentPageNumber, $numberOfPage) {
197
            $start = null;
198
            $begin = null;
199
            $end   = null;
200
            $numberOfLink = $this->config['nb_link'];
201
            if ($numberOfLink % 2 == 0) {
202
                $start = $currentPageNumber - ($numberOfLink / 2) + 1;
203
                $end   = $currentPageNumber + ($numberOfLink / 2);
204
            } else {
205
                $start = $currentPageNumber - floor($numberOfLink / 2);
206
                $end   = $currentPageNumber + floor($numberOfLink / 2);
207
            }
208
            if ($start <= 1) {
209
                $begin = 1;
210
                $end   = $numberOfLink;
211
            } else if ($start > 1 && $end < $numberOfPage) {
212
                $begin = $start;
213
            } else {
214
                $begin = ($numberOfPage - $numberOfLink) + 1;
215
                $end   = $numberOfPage;
216
            }
217
            if ($numberOfPage <= $numberOfLink) {
218
                $begin = 1;
219
                $end = $numberOfPage;
220
            }
221
            return array(
222
                        'begin' => (int) $begin,
223
                        'end' => (int) $end
224
                    );
225
        }
226
227
        /**
228
         * Build the pagination link for the page in the middle
229
         * @param  int $begin             the pagination begin number
230
         * @param  int $end               the pagination end number
231
         * @param  int $currentPageNumber the pagination current page number
232
         * @return string                    
233
         */
234
        protected function buildPaginationLinkForMiddlePage($begin, $end, $currentPageNumber) {
235
            $navbar = null;
236
            $query = $this->paginationQueryString;
237
            $navbar .= $this->config['previous_open'] 
238
                            . '<a href="' . $query . ($currentPageNumber - 1) . '">' 
239
                            . $this->config['previous_text'] . '</a>' . $this->config['previous_close'];
240
            for ($i = $begin; $i <= $end; $i++) {
241
                if ($i == $currentPageNumber) {
242
                    $navbar .= $this->config['active_link_open'] . $currentPageNumber . $this->config['active_link_close'];
243
                } else {
244
                    $navbar .= $this->config['digit_open'] 
245
                                    . '<a href="' . $query . $i . '"' 
246
                                    . attributes_to_string($this->config['attributes']) . '>' . $i . '</a>' 
247
                                    . $this->config['digit_close'];
248
                }
249
            }
250
            $navbar .= $this->config['next_open'] . '<a href="' . $query . ($currentPageNumber + 1) . '">' 
251
                       . $this->config['next_text'] . '</a>' . $this->config['next_close'];
252
            return $navbar;
253
        }
254
255
256
         /**
257
         * Build the pagination link for the first page
258
         * @see Pagination::buildPaginationLinkForFirstAndLastPage
259
         */
260
        protected function buildPaginationLinkForFirstPage($begin, $end, $currentPageNumber) {
261
            return $this->buildPaginationLinkForFirstAndLastPage($begin, $end, $currentPageNumber, 'first');
262
        }
263
264
        /**
265
         * Build the pagination link for the last page
266
         * @see Pagination::buildPaginationLinkForFirstAndLastPage
267
         */
268
        protected function buildPaginationLinkForLastPage($begin, $end, $currentPageNumber) {
269
            return $this->buildPaginationLinkForFirstAndLastPage($begin, $end, $currentPageNumber, 'last');
270
        }
271
272
        /**
273
         * Build the pagination link for the first and last page
274
         * 
275
         * @param  int $begin the pagination begin number
276
         * @param  int $end the pagination end number
277
         * @param  int $currentPageNumber the pagination current page number
278
         * @param string $type can be "first", "last"
279
         * 
280
         * @return string                    
281
         */
282
        protected function buildPaginationLinkForFirstAndLastPage($begin, $end, $currentPageNumber, $type = 'first') {
283
            $navbar = null;
284
            $query = $this->paginationQueryString;
285
            if ($type == 'last') {
286
                $navbar .= $this->config['previous_open'] 
287
                        . '<a href="' . $query . ($currentPageNumber - 1) . '">' 
288
                        . $this->config['previous_text'] . '</a>' . $this->config['previous_close'];
289
            }
290
            for ($i = $begin; $i <= $end; $i++) {
291
                if ($i == $currentPageNumber) {
292
                    $navbar .= $this->config['active_link_open'] . $currentPageNumber . $this->config['active_link_close'];
293
                } else {
294
                    $navbar .= $this->config['digit_open'] 
295
                            . '<a href="' . $query . $i . '"' 
296
                            . attributes_to_string($this->config['attributes']) . '>' . $i . '</a>' 
297
                            . $this->config['digit_close'];
298
                }
299
            }
300
            if ($type == 'first') {
301
                $navbar .= $this->config['next_open']
302
                            . '<a href="' . $query . ($currentPageNumber + 1) . '">' 
303
                            . $this->config['next_text'] . '</a>' . $this->config['next_close'];
304
            }
305
            return $navbar;
306
        }
307
    }
308