Passed
Push — master ( 160414...06ae89 )
by Bruno
12:11 queued 06:28
created

Pagination   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 78
c 1
b 0
f 0
dl 0
loc 134
rs 9.76
wmc 33

3 Methods

Rating   Name   Duplication   Size   Complexity  
C render() 0 70 12
A getItem() 0 9 1
F glue_url() 0 30 20
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
10
class Pagination extends Element
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 render(array $parameters, HTMLNode $previous): HTMLNode
20
    {
21
        $pagesaround = intval($parameters[self::PAGES_AROUND]) ?? 5;
22
        $perpage = intval($parameters[self::PER_PAGE]) ?? 20;
23
        $baseurl = $parameters[self::BASE_URL] ?? '?';
24
        $numitems = $parameters[self::TOTAL_ITEMS] ?? 0;
25
26
        // use $currentPage when defined
27
        if (array_key_exists(self::CURRENT_PAGE, $parameters)) {
28
            $currentPage = intval($parameters[self::CURRENT_PAGE]);
29
            $currentitem = $currentPage * ($perpage - 1);
30
        } else {
31
            $currentitem = intval($parameters[self::CURRENT]) ?? 0;
32
            $currentPage = ceil($currentitem / $perpage);
0 ignored issues
show
Unused Code introduced by
The assignment to $currentPage is dead and can be removed.
Loading history...
33
        }
34
    
35
        // $firstindex => first id, same as 'begin'
36
        $firstindex = $currentitem - $pagesaround * $perpage;
37
        if ($firstindex < 0) {
38
            $firstindex = 0;
39
        }
40
    
41
        $maxindex = $currentitem + $pagesaround * $perpage;
42
        if ($maxindex > $numitems) {
43
            $maxindex = $numitems;
44
        }
45
    
46
        // only one page? don't show anything.
47
        if ($maxindex <= $perpage) {
48
            return HTMLNode::factory('');
49
        }
50
    
51
        $query = array();
52
        $parsed = parse_url($baseurl);
53
        if ($parsed === false) {
54
            throw new Exception('Invalid url' . $baseurl);
55
        }
56
        if (isset($parsed['query'])) {
57
            mb_parse_str($parsed['query'], $query);
58
        }
59
60
        $pages = [];
61
62
        if ($firstindex > 0) {
63
            $pages[] = $this->getItem('...', '', 'formularium-ellipsis');
64
        }
65
    
66
        for ($i = $firstindex; $i < $maxindex; $i += $perpage) {
67
            $page = $i / $perpage + 1;
68
            if ($i < $currentitem && $i + $perpage >= $currentitem) {
69
                $pages[] = $this->getItem((string)$page, '', 'formularium-pagination-current');
70
            } else {
71
                $parsed['query'] = array_merge($query, array('begin' => $i, 'total' => $perpage));
72
                $baseurl = $this->glue_url($parsed);
73
                $pages[] = $this->getItem((string)$page, $baseurl);
74
            }
75
        }
76
    
77
        if ($i < $numitems) {
78
            // disabled
79
            $pages[] = $this->getItem('...', '', 'formularium-ellipsis');
80
        }
81
    
82
        return HTMLNode::factory(
83
            'nav',
84
            ['class' => 'formularium-pagination-wrapper', 'aria-label' => "Page navigation"],
85
            HTMLNode::factory(
86
                'ul',
87
                ['class' => 'formularium-pagination'],
88
                $pages
89
            )
90
        );
91
    }
92
93
    protected function getItem(string $text, string $link, string $class = ''): HTMLNode
94
    {
95
        return HTMLNode::factory(
96
            'li',
97
            ['class' => ['formularium-pagination-item', $class]],
98
            HTMLNode::factory(
99
                'a',
100
                ['class' => 'formularium-pagination-link', 'href' => $link],
101
                $text
102
            )
103
        );
104
    }
105
106
    /**
107
     * Inverse of parse_url.
108
     *
109
     * @codeCoverageIgnore
110
     * @param array $parsed An array of fields, same ones as returned by parse_url.
111
     * In addition, the 'query' field may be an associative array as well.
112
     * @return string The URL.
113
     */
114
    protected function glue_url(array $parsed): string
115
    {
116
        $uri = '';
117
        if (isset($parsed['scheme'])) {
118
            $uri = $parsed['scheme'] ?
119
            $parsed['scheme'] . ':' . ((mb_strtolower($parsed['scheme']) == 'mailto') ? '' : '//') : '';
120
        }
121
        if (isset($parsed['user'])) {
122
            $uri .= $parsed['user'] ? $parsed['user'] . ($parsed['pass'] ? ':' . $parsed['pass'] : '') . '@' : '';
123
        }
124
        if (isset($parsed['host'])) {
125
            $uri .= $parsed['host'] ? $parsed['host'] : '';
126
        }
127
        if (isset($parsed['port'])) {
128
            $uri .= $parsed['port'] ? ':' . $parsed['port'] : '';
129
        }
130
        if (isset($parsed['path'])) {
131
            $uri .= $parsed['path'] ? $parsed['path'] : '';
132
        }
133
        if (isset($parsed['query'])) {
134
            if (is_array($parsed['query'])) {
135
                $uri .= $parsed['query'] ? '?' . http_build_query($parsed['query']) : '';
136
            } elseif (is_string($parsed['query'])) {
137
                $uri .= $parsed['query'] ? '?' . $parsed['query'] : '';
138
            }
139
        }
140
        if (isset($parsed['fragment'])) {
141
            $uri .= $parsed['fragment'] ? '#' . $parsed['fragment'] : '';
142
        }
143
        return $uri;
144
    }
145
}
146