Pagination::glue_url()   F
last analyzed

Complexity

Conditions 20
Paths 12150

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 20
eloc 20
c 1
b 0
f 0
nc 12150
nop 1
dl 0
loc 30
rs 0

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