Completed
Pull Request — develop (#720)
by Imants
03:58
created

Paginator_Basic::recursiveRender()   F

Complexity

Conditions 24
Paths > 20000

Size

Total Lines 160
Code Lines 96

Duplication

Lines 14
Ratio 8.75 %

Importance

Changes 5
Bugs 3 Features 0
Metric Value
cc 24
c 5
b 3
f 0
dl 14
loc 160
rs 2
eloc 96
nc 45467
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Paginator needs to have source set (which can be either Model, DSQL or Array).
4
 * It will render itself into parent and will limit the source to display limited
5
 * number of records per page with ability to travel back and forth.
6
 */
7
class Paginator_Basic extends CompleteLister
8
{
9
    /**
10
     * How many records should we show per page.
11
     *
12
     * @var int
13
     */
14
    public $ipp = 30;
15
16
    /**
17
     * How many records should we skip. By default don't skip anything.
18
     *
19
     * @var int
20
     */
21
    public $skip = 0;
22
23
    /**
24
     * How many adjacent pages from current page should we show.
25
     *
26
     * @var int
27
     */
28
    public $range = 4;
29
30
    /**
31
     * Should we reload parent with AJAX ?
32
     *
33
     * @var bool
34
     */
35
    public $ajax_reload = true;
36
37
    /**
38
     * Should we remember page when user comes back ?
39
     *
40
     * @var bool
41
     */
42
    public $memorize = true;
43
44
    /**
45
     * GET argument to use to specify page
46
     *
47
     * @var string
48
     */
49
    public $skip_var = null;
50
51
    /**
52
     * Data source. Set with setSource().
53
     *
54
     * @var SQL_Model|Model|DB_dsql|mixed
55
     */
56
    public $source = null;
57
58
    /**
59
     * lSet this to nicely redefine base page
60
     *
61
     * @var string
62
     */
63
    public $base_page = null;
64
65
    /** @var int */
66
    public $found_rows;
67
    /** @var int */
68
    public $cur_page;
69
    /** @var int */
70
    public $total_pages;
71
72
    // {{{ Inherited properties
73
74
    /** @var View */
75
    public $owner;
76
77
    // }}}
78
79
    /**
80
     * Initialization.
81
     */
82
    public function init()
83
    {
84
        parent::init();
85
86
        if (!$this->skip_var) {
87
            $this->skip_var = $this->name.'_skip';
88
        }
89
        $this->skip_var = $this->_shorten($this->skip_var);
90
    }
91
92
    /**
93
     * Set number of items displayed per page.
94
     *
95
     * @param int $rows
96
     *
97
     * @return $this
98
     */
99
    public function setRowsPerPage($rows)
100
    {
101
        $this->ipp = $rows;
102
103
        return $this;
104
    }
105
106
    /**
107
     * @deprecated 4.3.2 use setRowsPerPage instead.
108
     */
109
    public function ipp($rows)
110
    {
111
        return $this->setRowsPerPage($rows);
112
    }
113
114
    /**
115
     * Set a custom source. Must be an object with foundRows() method.
116
     *
117
     * @param SQL_Model|Model|DB_dsql|mixed $source
118
     */
119
    public function setSource($source)
120
    {
121
        if ($this->memorize) {
122
            if (isset($_GET[$this->skip_var])) {
123
                $this->skip = $this->memorize('skip', (int) $_GET[$this->skip_var]);
124
            } else {
125
                $this->skip = (int) $this->recall('skip');
126
            }
127
        } else {
128
            $this->skip = @$_GET[$this->skip_var] + 0;
129
        }
130
131
        // Start iterating early ($source = DSQL of model)
132
        if ($source instanceof SQL_Model) {
133
            $source = $source->_preexec();
134
        }
135
136
        if ($source instanceof DB_dsql) {
137
            $source->limit($this->ipp, $this->skip);
138
            $source->calcFoundRows();
139
            $this->source = $source;
140
        } elseif ($source instanceof Model) {
141
            $this->source = $source->setLimit($this->ipp, $this->skip);
142
        } else {
143
            // NOTE: no limiting enabled for unknown data source
144
            $this->source = &$source;
145
        }
146
    }
147
148
    /**
149
     * Recursively render this view.
150
     */
151
    public function recursiveRender()
152
    {
153
        // get data source
154
        if (!$this->source) {
155
156
            // force grid sorting implemented in Grid_Advanced
157
            if ($this->owner instanceof Grid_Advanced) {
158
                $this->owner->getIterator();
159
            }
160
161
            // set data source for Paginator
162
            if ($this->owner->model) {
163
                $this->setSource($this->owner->model);
164
            } elseif ($this->owner->dq) {
165
                $this->setSource($this->owner->dq);
166
            } else {
167
                throw $this->exception('Unable to find source for Paginator');
168
            }
169
        }
170
171
        // calculate found rows
172
        if ($this->source instanceof DB_dsql) {
173
            $this->source->preexec();
174
            $this->found_rows = $this->source->foundRows();
175
        } elseif ($this->source instanceof Model) {
176
            $this->found_rows = (int) $this->source->count();
177
        } else {
178
            $this->found_rows = count($this->source);
179
        }
180
181
        // calculate current page and total pages
182
        $this->cur_page = (int) floor($this->skip / $this->ipp) + 1;
183
        $this->total_pages = (int) ceil($this->found_rows / $this->ipp);
184
185
        if ($this->cur_page > $this->total_pages || ($this->cur_page == 1 && $this->skip != 0)) {
186
            $this->cur_page = 1;
187
            if ($this->memorize) {
188
                $this->memorize('skip', $this->skip = 0);
189
            }
190
            if ($this->source instanceof DB_dsql) {
191
                $this->source->limit($this->ipp, $this->skip);
192
                $this->source->rewind();                 // re-execute the query
193
            } elseif ($this->source instanceof Model) {
194
                $this->source->setLimit($this->ipp, $this->skip);
195
            } else {
196
                // Imants: not sure if this is correct, but it was like this before
197
                $this->source->setLimit($this->ipp, $this->skip);
198
            }
199
        }
200
201
        // no need for paginator if there is only one page
202
        if ($this->total_pages <= 1) {
203
            return $this->destroy();
204
        }
205
206
        if ($this->cur_page > 1) {
207
            /** @type View $v */
208
            $v = $this->add('View', null, 'prev');
209
            $v->setElement('a')
210
                ->setAttr('href', $this->app->url(
211
                    $this->base_page,
212
                    $u = array($this->skip_var => $pn = max(0, $this->skip - $this->ipp))
213
                ))
214
                ->setAttr('data-skip', $pn)
215
                ->set('« Prev')
216
                ;
217
        } else {
218
            $this->template->tryDel('prev');
219
        }
220
221
        if ($this->cur_page < $this->total_pages) {
222
            /** @type View $v */
223
            $v = $this->add('View', null, 'next');
224
            $v->setElement('a')
225
                ->setAttr('href', $this->app->url(
226
                    $this->base_page,
227
                    $u = array($this->skip_var => $pn = $this->skip + $this->ipp)
228
                ))
229
                ->setAttr('data-skip', $pn)
230
                ->set('Next »')
231
                ;
232
        } else {
233
            $this->template->tryDel('next');
234
        }
235
236
        // First page
237
        if ($this->cur_page > $this->range + 1) {
238
            /** @type View $v */
239
            $v = $this->add('View', null, 'first');
240
            $v->setElement('a')
241
                ->setAttr('href', $this->app->url(
242
                    $this->base_page,
243
                    $u = array($this->skip_var => $pn = max(0, 0))
244
                ))
245
                ->setAttr('data-skip', $pn)
246
                ->set('1')
247
                ;
248 View Code Duplication
            if ($this->cur_page > $this->range + 2) {
249
                /** @type View $v */
250
                $v = $this->add('View', null, 'points_left');
251
                $v->setElement('span')
252
                    ->set('...')
253
                    ;
254
            }
255
        }
256
257
        // Last page
258
        if ($this->cur_page < $this->total_pages - $this->range) {
259
            /** @type View $v */
260
            $v = $this->add('View', null, 'last');
261
            $v->setElement('a')
262
                ->setAttr('href', $this->app->url(
263
                    $this->base_page,
264
                    $u = array($this->skip_var => $pn = max(0, ($this->total_pages - 1) * $this->ipp))
265
                ))
266
                ->setAttr('data-skip', $pn)
267
                ->set($this->total_pages)
268
                ;
269 View Code Duplication
            if ($this->cur_page < $this->total_pages - $this->range - 1) {
270
                /** @type View $v */
271
                $v = $this->add('View', null, 'points_right');
272
                $v->setElement('span')
273
                    ->set('...')
274
                    ;
275
            }
276
        }
277
278
        // generate source for Paginator Lister (pages, links, labels etc.)
279
        $data = array();
280
281
        //setting cur as array seems not working in atk4.3. String is working
282
        $tplcur = $this->template->get('cur');
283
        $tplcur = (isset($tplcur[0])) ? $tplcur[0] : '';
284
285
        $range = range(
286
            max(1, $this->cur_page - $this->range),
287
            min($this->total_pages, $this->cur_page + $this->range)
288
        );
289
        foreach ($range as $p) {
290
            $data[] = array(
291
                'href' => $this->app->url($this->base_page, array($this->skip_var => $pn = ($p - 1) * $this->ipp)),
292
                'pn' => $pn,
293
                'cur' => $p == $this->cur_page ? $tplcur : '',
294
                'label' => $p,
295
            );
296
        }
297
298
        if ($this->ajax_reload) {
299
            $this->js(
300
                'click',
301
                $this->owner->js()->reload(
302
                    array($this->skip_var => $this->js()->_selectorThis()->attr('data-skip'))
303
                )
304
            )->_selector('#'.$this->name.' a');
305
        }
306
307
        parent::setSource($data);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (setSource() instead of recursiveRender()). Are you sure this is correct? If so, you might want to change this to $this->setSource().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
308
309
        return parent::recursiveRender();
310
    }
311
312
    /**
313
     * Set default template.
314
     *
315
     * @return array|string
316
     */
317
    public function defaultTemplate()
318
    {
319
        return array('paginator42', 'paginator');
320
    }
321
322
    /**
323
     * Set default spot.
324
     *
325
     * @return string
326
     */
327
    public function defaultSpot()
328
    {
329
        return 'Paginator';
330
    }
331
}
332