Passed
Push — master ( 06ff70...f55fb8 )
by Bruno
05:48
created

Renderable_pagination::pagination()   F

Complexity

Conditions 14
Paths 416

Size

Total Lines 78
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
cc 14
eloc 48
c 4
b 0
f 1
nc 416
nop 3
dl 0
loc 78
rs 2.911

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 declare(strict_types=1);
2
3
namespace Formularium\Frontend\HTML\Renderable;
4
5
use Formularium\Exception\Exception;
6
use Formularium\Field;
7
use Formularium\HTMLElement;
8
use PHP_CodeSniffer\Generators\HTML;
9
10
class Renderable_pagination extends Renderable_constant
11
{
12
    const BASE_URL = 'baseURL'; // base url for pagination. Default: '?'
13
    const CURRENT = 'current'; // current item. Conflicts with CURRENT_PAGE, use just one
14
    const CURRENT_PAGE = 'currentPage'; // current page. Conflicts with CURRENT, use just one
15
    const PAGES_AROUND = 'pagesAround'; // maximum pages listed before or after the current one
16
    const PER_PAGE = 'perPage'; // items per page. Default: 20
17
    const TOTAL_ITEMS = 'totalItems'; // total items in query.
18
19
    public function viewable($value, Field $field, HTMLElement $previous): HTMLElement
20
    {
21
        return $this->container($this->pagination($value, $field, $previous), $field);
22
    }
23
    
24
    public function editable($value, Field $field, HTMLElement $previous): HTMLElement
25
    {
26
        return $this->container($this->pagination($value, $field, $previous), $field);
27
    }
28
29
    /**
30
     * @param mixed $value
31
     * @param Field $field
32
     * @param HTMLElement $previous
33
     * @return HTMLElement
34
     */
35
    protected function pagination($value, Field $field, HTMLElement $previous): HTMLElement
36
    {
37
        if (!is_array($value)) {
38
            $value = [];
39
        }
40
        
41
        $pagesaround = intval(
42
            $value[self::PAGES_AROUND] ?? $field->getRenderable(self::PAGES_AROUND, 5)
43
        );
44
        $perpage = intval(
45
            $value[self::PER_PAGE] ?? $field->getRenderable(self::PER_PAGE, 20)
46
        );
47
        $baseurl = $value[self::BASE_URL] ?? $field->getRenderable(self::BASE_URL, '?');
48
        $numitems = $value[self::TOTAL_ITEMS] ?? $field->getRenderable(self::TOTAL_ITEMS, 0);
49
50
        // use $currentPage when defined
51
        if (array_key_exists(self::CURRENT_PAGE, $value) || $field->getRenderable(self::CURRENT_PAGE, null) !== null) {
52
            $currentPage = $value[self::CURRENT_PAGE] ?? intval($field->getRenderable(self::CURRENT_PAGE, 1));
53
            $currentitem = $currentPage * ($perpage - 1);
54
        } else {
55
            $currentitem = $value[self::CURRENT] ?? intval($field->getRenderable(self::CURRENT, 0));
56
            $currentPage = ceil($currentitem / $perpage);
0 ignored issues
show
Unused Code introduced by
The assignment to $currentPage is dead and can be removed.
Loading history...
57
        }
58
    
59
        // $firstindex => first id, same as 'begin'
60
        $firstindex = $currentitem - $pagesaround * $perpage;
61
        if ($firstindex < 0) {
62
            $firstindex = 0;
63
        }
64
    
65
        $maxindex = $currentitem + $pagesaround * $perpage;
66
        if ($maxindex > $numitems) {
67
            $maxindex = $numitems;
68
        }
69
    
70
        // only one page? don't show anything.
71
        if ($maxindex <= $perpage) {
72
            return HTMLElement::factory('');
73
        }
74
    
75
        $query = array();
76
        $parsed = parse_url($baseurl);
77
        if ($parsed === false) {
78
            throw new Exception('Invalid url' . $baseurl);
79
        }
80
        if (isset($parsed['query'])) {
81
            mb_parse_str($parsed['query'], $query);
82
        }
83
84
        $pages = [];
85
86
        if ($firstindex > 0) {
87
            $pages[] = $this->getItem('...', '', 'formularium-ellipsis');
88
        }
89
    
90
        for ($i = $firstindex; $i < $maxindex; $i += $perpage) {
91
            $page = $i / $perpage + 1;
92
            if ($i < $currentitem && $i + $perpage >= $currentitem) {
93
                $pages[] = $this->getItem((string)$page, '', 'formularium-pagination-current');
94
            } else {
95
                $parsed['query'] = array_merge($query, array('begin' => $i, 'total' => $perpage));
96
                $baseurl = $this->glue_url($parsed);
97
                $pages[] = $this->getItem((string)$page, $baseurl);
98
            }
99
        }
100
    
101
        if ($i < $numitems) {
102
            // disabled
103
            $pages[] = $this->getItem('...', '', 'formularium-ellipsis');
104
        }
105
    
106
        return HTMLElement::factory(
107
            'nav',
108
            ['class' => 'formularium-pagination-wrapper', 'aria-label' => "Page navigation"],
109
            HTMLElement::factory(
110
                'ul',
111
                ['class' => 'formularium-pagination'],
112
                $pages
113
            )
114
        );
115
    }
116
117
    protected function getItem(string $text, string $link, string $class = ''): HTMLElement
118
    {
119
        return HTMLElement::factory(
120
            'li',
121
            ['class' => ['formularium-pagination-item', $class]],
122
            HTMLElement::factory(
123
                'a',
124
                ['class' => 'formularium-pagination-link', 'href' => $link],
125
                $text
126
            )
127
        );
128
    }
129
130
131
    /**
132
     * Inverse of parse_url.
133
     * @param array $parsed An array of fields, same ones as returned by parse_url.
134
     * In addition, the 'query' field may be an associative array as well.
135
     * @return string The URL.
136
     */
137
    protected function glue_url(array $parsed): string
138
    {
139
        $uri = '';
140
        if (isset($parsed['scheme'])) {
141
            $uri = $parsed['scheme'] ?
142
            $parsed['scheme'] . ':' . ((mb_strtolower($parsed['scheme']) == 'mailto') ? '' : '//') : '';
143
        }
144
        if (isset($parsed['user'])) {
145
            $uri .= $parsed['user'] ? $parsed['user'] . ($parsed['pass'] ? ':' . $parsed['pass'] : '') . '@' : '';
146
        }
147
        if (isset($parsed['host'])) {
148
            $uri .= $parsed['host'] ? $parsed['host'] : '';
149
        }
150
        if (isset($parsed['port'])) {
151
            $uri .= $parsed['port'] ? ':' . $parsed['port'] : '';
152
        }
153
        if (isset($parsed['path'])) {
154
            $uri .= $parsed['path'] ? $parsed['path'] : '';
155
        }
156
        if (isset($parsed['query'])) {
157
            if (is_array($parsed['query'])) {
158
                $uri .= $parsed['query'] ? '?' . http_build_query($parsed['query']) : '';
159
            } elseif (is_string($parsed['query'])) {
160
                $uri .= $parsed['query'] ? '?' . $parsed['query'] : '';
161
            }
162
        }
163
        if (isset($parsed['fragment'])) {
164
            $uri .= $parsed['fragment'] ? '#' . $parsed['fragment'] : '';
165
        }
166
        return $uri;
167
    }
168
}
169