Passed
Branch master (cbf361)
by Mihail
04:19
created

SimplePagination::display()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 67
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 33
nc 6
nop 1
dl 0
loc 67
rs 7.0237
c 0
b 0
f 0

How to fix   Long Method   

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
namespace Ffcms\Core\Helper\HTML;
4
5
use Ffcms\Core\Helper\Type\Any;
6
use Ffcms\Core\Helper\Type\Arr;
7
use Ffcms\Core\Helper\Type\Obj;
8
9
/**
10
 * Class SimplePagination. Build and display html pagination block
11
 * @package Ffcms\Core\Helper\HTML
12
 */
13
class SimplePagination
14
{
15
    protected $url;
16
    protected $page;
17
    protected $step;
18
    protected $total;
19
20
    /**
21
     * SimplePagination constructor. Parse passed elements
22
     * @param array $elements
23
     */
24
    public function __construct(array $elements)
25
    {
26
        $this->url = $elements['url'];
27
        $this->page = (int)$elements['page'];
28
        $this->step = (int)$elements['step'] > 0 ? (int)$elements['step'] : 5;
29
        $this->total = (int)$elements['total'];
30
    }
31
32
    /**
33
     * Display pagination html code. Must be initialized via (new SimplePagination([params]))->display(['class' => 'test'])
34
     * @param array|null $property
35
     * @return null|string
36
     */
37
    public function display(array $property = null): ?string
38
    {
39
        // total items is less to pagination requirement
40
        if (($this->page * $this->step) + 1 > $this->total) {
41
            return null;
42
        }
43
44
        $lastPage = ceil($this->total / $this->step); // 6/5 ~ 2 = 0..2
45
46
        if ($lastPage <= 1) {
47
            return null;
48
        }
49
50
        // prevent hack-boy's any try
51
        if ($this->page > $lastPage) {
52
            return null;
53
        }
54
55
        $items = [];
56
        // more then 10 items in pagination
57
        if ($lastPage > 10) {
58
            if ($this->page < 4 || $lastPage - $this->page <= 4) { // list start, page in [0..4]
59
                // from start to 4
60
                $items = $this->generateItems(0, 4);
61
62
                // add "..." button
63
                $items[] = [
64
                    'type' => 'link', 'link' => '#', 'text' => '...', 'property' => ['class' => 'disabled']
65
                ];
66
                // add middle page
67
                $middlePage = ceil($lastPage / 2);
68
                $items[] = [
69
                    'type' => 'link', 'link' => $this->setUrlPage($middlePage), 'text' => $middlePage + 1
70
                ];
71
                // add "..." button
72
                $items[] = [
73
                    'type' => 'link', 'link' => '#', 'text' => '...', 'property' => ['class' => 'disabled']
74
                ];
75
                $items = Arr::merge($items, $this->generateItems($lastPage - 4, $lastPage));
0 ignored issues
show
Bug introduced by
$lastPage of type double is incompatible with the type integer expected by parameter $end of Ffcms\Core\Helper\HTML\S...nation::generateItems(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
                $items = Arr::merge($items, $this->generateItems($lastPage - 4, /** @scrutinizer ignore-type */ $lastPage));
Loading history...
Bug introduced by
$lastPage - 4 of type double is incompatible with the type integer expected by parameter $start of Ffcms\Core\Helper\HTML\S...nation::generateItems(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
                $items = Arr::merge($items, $this->generateItems(/** @scrutinizer ignore-type */ $lastPage - 4, $lastPage));
Loading history...
76
            } else { // meanwhile on middle
77
                // generate 1-2 pages
78
                $items = $this->generateItems(0, 2);
79
80
                // add "..." button
81
                $items[] = [
82
                    'type' => 'link', 'link' => '#', 'text' => '...', 'property' => ['class' => 'disabled']
83
                ];
84
85
                // add middle variance -3..mid..+3
86
                $items = Arr::merge($items, $this->generateItems($this->page - 3, $this->page + 3));
87
88
                // add "..." button
89
                $items[] = [
90
                    'type' => 'link', 'link' => '#', 'text' => '...', 'property' => ['class' => 'disabled']
91
                ];
92
93
                // add latest 2 items
94
                $items = Arr::merge($items, $this->generateItems($lastPage - 2, $lastPage));
95
            }
96
        } else { // less then 10 items in pagination
97
            $items = $this->generateItems(0, $lastPage);
98
        }
99
100
        return Listing::display([
101
            'type' => 'ul',
102
            'property' => $property,
103
            'items' => $items
104
        ]);
105
    }
106
107
    /**
108
     * Set GET param to property array
109
     * @param int|string $pageId
110
     * @return array
111
     */
112
    protected function setUrlPage($pageId)
113
    {
114
        $url = $this->url;
115
        switch (count($url)) { // check nulls if not set
116
            case 1: // only controller/action is defined
117
                $url[1] = null;
118
                $url[2] = null;
119
                break;
120
            case 2:
121
                $url[2] = null;
122
                break;
123
        }
124
125
        // add page param if > 0
126
        if ((int)$pageId > 0) {
127
            // merge with ?page if query is not empty
128
            $url[3] = (Any::isArray($url[3]) ? Arr::merge($url[3], ['page' => $pageId]) : ['page' => $pageId]);
129
        }
130
131
        return $url;
132
    }
133
134
    /**
135
     * Generate item array to build pagination listing
136
     * @param int $start
137
     * @param int $end
138
     * @return array|null
139
     */
140
    protected function generateItems($start, $end)
141
    {
142
        // prevent any shit's
143
        if ($end <= $start) {
144
            return null;
145
        }
146
147
        $items = [];
148
        for ($i = $start; $i < $end; $i++) {
149
            $items[] = [
150
                'type' => 'link', 'link' => $this->setUrlPage($i), 'text' => $i + 1
151
            ];
152
        }
153
        return $items;
154
    }
155
}
156