Component   C
last analyzed

Complexity

Total Complexity 75

Size/Duplication

Total Lines 236
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 75
c 1
b 0
f 0
lcom 1
cbo 1
dl 0
loc 236
ccs 169
cts 169
cp 1
rs 5.5056

8 Methods

Rating   Name   Duplication   Size   Complexity  
C __get() 0 25 16
C set() 0 27 7
A total() 0 6 3
A html() 0 8 3
F links() 0 55 22
A page() 0 8 2
B __construct() 0 47 5
D pager() 0 28 17

How to fix   Complexity   

Complex Class

Complex classes like Component often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Component, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace BootPress\Pagination;
4
5
use BootPress\Page\Component as Page;
6
7
class Component
8
{
9
    private $page;
10
    private $get;
11
    private $url;
12
    private $start;
13
    private $limit; // formerly $display
14
    private $total; // formerly $num_pages
15
    private $current;
16
    private $links = array(
17
        'wrapper' => '<ul class="pagination">%s</ul>',
18
        'link' => '<li><a href="%s">%s</a></li>',
19
        'active' => '<li class="active"><span>%s</span></li>',
20
        'disabled' => '<li class="disabled"><span>%s</span></li>',
21
        'previous' => '&laquo;',
22
        'next' => '&raquo;',
23
        'dots' => '&hellip;',
24
    );
25
    private $pager = array(
26
        'wrapper' => '<ul class="pager">%s</ul>',
27
        'previous' => '<li class="previous"><a href="%s">&laquo; %s</a></li>',
28
        'next' => '<li class="next"><a href="%s">%s &raquo;</a></li>',
29
    );
30
31 20
    public function __construct($framework = 'bootstrap') // http://getbootstrap.com/components/#pagination
32
    {
33 20
        $this->page = Page::html();
34 20
        $this->get = false;
35 20
        $this->set();
36
        switch ($framework) {
37 20
            case 'zurb_foundation': // http://foundation.zurb.com/docs/components/pagination.html
38 1
                $this->html('links', array(
39 1
                    'active' => '<li class="current"><a href="">%s</a></li>',
40 1
                    'disabled' => '<li class="unavailable"><a href="">%s</a></li>',
41 1
                ));
42 1
                break;
43 19
            case 'semantic_ui': // http://semantic-ui.com/collections/menu.html#pagination
44 1
                $this->html('links', array(
45 1
                    'wrapper' => '<div class="ui pagination menu">%s</div>',
46 1
                    'link' => '<a class="item" href="%s">%s</a>',
47 1
                    'active' => '<div class="active item">%s</div>',
48 1
                    'disabled' => '<div class="disabled item">%s</div>',
49 1
                    'previous' => '<i class="left arrow icon"></i>',
50 1
                    'next' => '<i class="right arrow icon"></i>',
51 1
                ));
52 1
                break;
53 18
            case 'materialize': // http://materializecss.com/pagination.html
54 1
                $this->html('links', array(
55 1
                    'link' => '<li class="waves-effect"><a href="%s">%s</a></li>',
56 1
                    'active' => '<li class="active"><a href="#!">%s</a></li>',
57 1
                    'disabled' => '<li class="disabled"><a href="#!">%s</a></li>',
58 1
                    'previous' => '<i class="material-icons">keyboard_arrow_left</i>',
59 1
                    'next' => '<i class="material-icons">keyboard_arrow_right</i>',
60 1
                ));
61 1
                break;
62 17
            case 'uikit': // http://getuikit.com/docs/pagination.html
63 1
                $this->html('links', array(
64 1
                    'wrapper' => '<ul class="uk-pagination">%s</ul>',
65 1
                    'active' => '<li class="uk-active"><span>%s</span></li>',
66 1
                    'disabled' => '<li class="uk-disabled"><span>%s</span></li>',
67 1
                    'previous' => '<i class="uk-icon-angle-double-left"></i>',
68 1
                    'next' => '<i class="uk-icon-angle-double-right"></i>',
69 1
                ));
70 1
                $this->html('pager', array(
71 1
                    'wrapper' => '<ul class="uk-pagination">%s</ul>',
72 1
                    'previous' => '<li class="uk-pagination-previous"><a href="%s"><i class="uk-icon-angle-double-left"></i> %s</a></li>',
73 1
                    'next' => '<li class="uk-pagination-next"><a href="%s">%s <i class="uk-icon-angle-double-right"></i></a></li>',
74 1
                ));
75 1
                break;
76
        }
77 20
    }
78
79 15
    public function __get($name)
80
    {
81
        switch ($name) {
82 15
            case 'limit':
83 15
                return ($this->get) ? ' LIMIT '.$this->start.', '.$this->limit : '';
84
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
85 4
            case 'last_page':
86 4
                return ($this->get && $this->current == $this->total) ? true : false;
87
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
88 4
            case 'current_page':
89 4
                return ($this->get) ? $this->current : 1;
90
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
91 4
            case 'number_pages':
92 4
                return ($this->get) ? $this->total : 1;
93
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
94 4
            case 'previous_url':
95 4
                return ($this->get && $this->current > 1) ? $this->page($this->current - 1) : '';
96
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
97 4
            case 'next_url':
98 4
                return ($this->get && $this->current < $this->total) ? $this->page($this->current + 1) : '';
99
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
100
        }
101
102 1
        return;
103
    }
104
105 21
    public function set($page = 'page', $limit = 10, $url = null)
106
    {
107 21
        if (is_null($url)) {
108 21
            $url = $this->page->url();
109 21
        }
110 21
        $params = $this->page->url('params', $url);
111 21
        $this->get = $page;
112 21
        $this->url = $url;
113 21
        $this->start = 0;
114 21
        $this->limit = $limit;
115 21
        $this->total = 1;
116 21
        $this->current = 1;
117 21
        if (isset($params[$page])) {
118 6
            $page = array_map('intval', explode('of', $params[$page]));
119 6
            if (($current = array_shift($page)) && $current > 1) { // not the first page
120 6
                $this->current = $current;
121 6
                $this->start = ($current - 1) * $this->limit;
122 6
                if (($total = array_shift($page)) && $current < $total) { // and not the last page
123 5
                    $this->total = $total;
124
125 5
                    return true;
126
                }
127 2
            }
128 2
        }
129
130 21
        return false;
131
    }
132
133 13
    public function total($count)
134
    {
135 13
        if ($this->get) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->get of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
136 13
            $this->total = ($count > $this->limit) ? ceil($count / $this->limit) : 1;
137 13
        }
138 13
    }
139
140 4
    public function html($type, array $options)
141
    {
142 4
        if ($type == 'links') {
143 4
            $this->links = array_merge($this->links, $options);
144 4
        } elseif ($type == 'pager') {
145 1
            $this->pager = array_merge($this->pager, $options);
146 1
        }
147 4
    }
148
149 7
    public function links($pad = 3, $array = false)
150
    {
151 7
        if ($this->get === false || $this->total === 1) {
152 1
            return '';
153
        }
154 7
        $begin = $this->current - $pad;
155 7
        $end = $this->current + $pad;
156 7
        if ($begin < 1) {
157 5
            $begin = 1;
158 5
            $end = $pad * 2 + 1;
159 5
        }
160 7
        if ($end > $this->total) {
161 1
            $end = $this->total;
162 1
            $begin = $end - ($pad * 2);
163 1
            if ($begin < 1) {
164 1
                $begin = 1;
165 1
            }
166 1
        }
167 7
        $links = array();
168 7
        if (!empty($this->links['dots']) && $begin > 1) {
169 2
            $links[] = sprintf($this->links['link'], $this->page(1), 1);
170 2
            if ($begin == 3) {
171 1
                $links[] = sprintf($this->links['link'], $this->page(2), 2);
172 2
            } elseif ($begin != 2) {
173 1
                $links[] = sprintf($this->links['disabled'], $this->links['dots']);
174 1
            }
175 2
        }
176 7
        for ($num = $begin; $num <= $end; ++$num) {
177 7
            if ($num == $this->current) {
178 7
                $links[] = sprintf($this->links['active'], $num);
179 7
            } else {
180 7
                $links[] = sprintf($this->links['link'], $this->page($num), $num);
181
            }
182 7
        }
183 7
        if (!empty($this->links['dots']) && $end < $this->total) {
184 7
            if ($end == ($this->total - 2)) {
185 1
                $links[] = sprintf($this->links['link'], $this->page($this->total - 1), $this->total - 1);
186 7
            } elseif ($end != ($this->total - 1)) {
187 5
                $links[] = sprintf($this->links['disabled'], $this->links['dots']);
188 5
            }
189 7
            $links[] = sprintf($this->links['link'], $this->page($this->total), $this->total);
190 7
        }
191 7
        if ($array === false) {
192 6
            if (!empty($this->links['previous']) && $this->current > 1) {
193 5
                array_unshift($links, sprintf($this->links['link'], $this->page($this->current - 1), $this->links['previous']));
194 5
            }
195 6
            if (!empty($this->links['next']) && $this->current < $this->total) {
196 6
                $links[] = sprintf($this->links['link'], $this->page($this->current + 1), $this->links['next']);
197 6
            }
198
199 6
            return (!empty($links)) ? "\n".sprintf($this->links['wrapper'], "\n\t".implode("\n\t", $links)."\n") : '';
200
        }
201
202 1
        return $links;
203
    }
204
205 17
    public function pager($previous = 'Previous', $next = 'Next')
206
    {
207 17
        $links = '';
208 17
        if (!empty($previous)) {
209 15
            if (is_array($previous)) {
210 3
                if (isset($previous['url']) && isset($previous['title'])) {
211 3
                    $links .= sprintf($this->pager['previous'], $previous['url'], $previous['title']);
212 3
                }
213 15
            } elseif (is_string($previous)) {
214 12
                if ($this->get && $this->total > 1 && $this->current > 1) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->get of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
215 1
                    $links .= sprintf($this->pager['previous'], $this->page($this->current - 1), $previous);
216 1
                }
217 12
            }
218 15
        }
219 17
        if (!empty($next)) {
220 15
            if (is_array($next)) {
221 3
                if (isset($next['url']) && isset($next['title'])) {
222 3
                    $links .= sprintf($this->pager['next'], $next['url'], $next['title']);
223 3
                }
224 15
            } elseif (is_string($next)) {
225 12
                if ($this->get && $this->current < $this->total) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->get of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
226 2
                    $links .= sprintf($this->pager['next'], $this->page($this->current + 1), $next);
227 2
                }
228 12
            }
229 15
        }
230
231 17
        return (!empty($links)) ? "\n".sprintf($this->pager['wrapper'], $links) : '';
232
    }
233
234 7
    private function page($num)
235
    {
236 7
        if ($num == 1) {
237 6
            return $this->page->url('delete', $this->url, $this->get);
238
        }
239
240 7
        return $this->page->url('add', $this->url, $this->get, $num.'of'.$this->total);
241
    }
242
}
243