blib/lib/Template/Plugin/Bootstrap/Pagination.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 101 | 103 | 98.0 |
branch | 46 | 48 | 95.8 |
condition | 23 | 30 | 76.6 |
subroutine | 17 | 17 | 100.0 |
pod | 3 | 3 | 100.0 |
total | 190 | 201 | 94.5 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package Template::Plugin::Bootstrap::Pagination; | ||||||
2 | { | ||||||
3 | $Template::Plugin::Bootstrap::Pagination::VERSION = '0.002000'; | ||||||
4 | } | ||||||
5 | 1 | 1 | 36146 | use parent qw(Template::Plugin); | |||
1 | 279 | ||||||
1 | 5 | ||||||
6 | |||||||
7 | # ABSTRACT: Produce HTML suitable for the Bootstrap pagination component | ||||||
8 | |||||||
9 | 1 | 1 | 930 | use strict; | |||
1 | 3 | ||||||
1 | 50 | ||||||
10 | 1 | 1 | 5 | use warnings; | |||
1 | 2 | ||||||
1 | 20 | ||||||
11 | |||||||
12 | 1 | 1 | 4 | use Carp; | |||
1 | 1 | ||||||
1 | 51 | ||||||
13 | 1 | 1 | 420 | use MRO::Compat; | |||
1 | 2095 | ||||||
1 | 23 | ||||||
14 | 1 | 1 | 505 | use HTML::Entities; | |||
1 | 4660 | ||||||
1 | 67 | ||||||
15 | 1 | 1 | 6 | use Scalar::Util qw(blessed); | |||
1 | 1 | ||||||
1 | 34 | ||||||
16 | 1 | 1 | 4 | use Template::Exception; | |||
1 | 1 | ||||||
1 | 841 | ||||||
17 | |||||||
18 | |||||||
19 | sub new { | ||||||
20 | 10 | 10 | 1 | 54277 | my ($class, $context, $arg_ref) = @_; | ||
21 | |||||||
22 | 10 | 40 | my $self = $class->next::method($context, $arg_ref); | ||||
23 | |||||||
24 | 10 | 50 | 66 | 174 | if (defined $arg_ref && ref $arg_ref ne 'HASH') { | ||
25 | 0 | 0 | $self->_throw('Hash reference required'); | ||||
26 | } | ||||||
27 | 10 | 100 | 33 | $arg_ref ||= {}; | |||
28 | 10 | 65 | $self->{default} = { | ||||
29 | prev_text => '«', | ||||||
30 | next_text => '»', | ||||||
31 | centered => 0, | ||||||
32 | right => 0, | ||||||
33 | siblings => 3, | ||||||
34 | offset => 0, | ||||||
35 | factor => 1, | ||||||
36 | version => 2, | ||||||
37 | 10 | 11 | %{$arg_ref}, | ||||
38 | }; | ||||||
39 | |||||||
40 | 10 | 31 | return $self; | ||||
41 | } | ||||||
42 | |||||||
43 | |||||||
44 | |||||||
45 | sub pagination { | ||||||
46 | 12 | 12 | 1 | 1134 | my ($self, $arg_ref) = @_; | ||
47 | |||||||
48 | 12 | 30 | $arg_ref = { | ||||
49 | 12 | 100 | 67 | %{$self->{default}}, | |||
50 | 12 | 13 | %{$arg_ref || {}}, | ||||
51 | }; | ||||||
52 | |||||||
53 | 12 | 22 | my $pager = $arg_ref->{pager}; | ||||
54 | 12 | 100 | 66 | 84 | unless (blessed $pager && $pager->isa('Data::Page')) { | ||
55 | 1 | 2 | $self->_throw("Required 'pager' parameter not passed or not a 'Data::Page' instance"); | ||||
56 | } | ||||||
57 | |||||||
58 | 11 | 14 | my $pagination = ''; | ||||
59 | 11 | 100 | 21 | if ($pager->total_entries() > $pager->entries_per_page()) { | |||
60 | 5 | 69 | my $current_page = $pager->current_page(); | ||||
61 | 5 | 160 | my $first_page = $pager->first_page(); | ||||
62 | 5 | 15 | my $last_page = $pager->last_page(); | ||||
63 | 5 | 66 | my $page = $first_page; | ||||
64 | 5 | 10 | PAGE: while ($page <= $last_page) { | ||||
65 | 20 | 100 | 26 | if ($current_page == $page) { | |||
66 | 5 | 10 | $pagination .= ' |
||||
67 | . ''.$page.'' | ||||||
68 | . ''; | ||||||
69 | } | ||||||
70 | else { | ||||||
71 | 15 | 100 | 100 | 83 | if ($page == $first_page || $page == $last_page | ||
100 | 100 | ||||||
66 | |||||||
100 | |||||||
72 | || abs($page - $current_page) <= ($arg_ref->{siblings}) | ||||||
73 | || $last_page <= (2 * $arg_ref->{siblings} + 1)) { | ||||||
74 | 11 | 16 | $pagination .= ' |
||||
75 | . ''.$page.'' | ||||||
76 | . ''; | ||||||
77 | } | ||||||
78 | elsif ($first_page + 1 == $page || $last_page - 1 == $page) { | ||||||
79 | 2 | 3 | $pagination .= ' |
||||
80 | . '…' | ||||||
81 | . ''; | ||||||
82 | } | ||||||
83 | else { | ||||||
84 | 2 | 100 | 4 | $page = ($page < $current_page) | |||
85 | ? $current_page - $arg_ref->{siblings} | ||||||
86 | : $last_page - 1; | ||||||
87 | 2 | 4 | next PAGE; | ||||
88 | } | ||||||
89 | } | ||||||
90 | 17 | 114 | $page++; | ||||
91 | } | ||||||
92 | } | ||||||
93 | |||||||
94 | 10 | 50 | 98 | my $version = $arg_ref->{version} || 2; | |||
95 | 10 | 100 | 22 | if ($version eq '2') { | |||
50 | |||||||
96 | 6 | 14 | return $self->_pagination_2($pagination, $arg_ref); | ||||
97 | } elsif ($version eq '3') { | ||||||
98 | 4 | 7 | return $self->_pagination_3($pagination, $arg_ref); | ||||
99 | } else { | ||||||
100 | 0 | 0 | croak('Bootstrap version ' . $version . ' not (yet) supported'); | ||||
101 | } | ||||||
102 | } | ||||||
103 | |||||||
104 | sub _pagination_2 { | ||||||
105 | 6 | 6 | 7 | my ($self, $pagination, $arg_ref) = @_; | |||
106 | |||||||
107 | 6 | 100 | 13 | my $alignment = $arg_ref->{centered} | |||
100 | |||||||
108 | ? ' pagination-centered' | ||||||
109 | : ($arg_ref->{right} ? ' pagination-right' : ''); | ||||||
110 | 6 | 100 | 10 | my $size = defined $arg_ref->{size} ? ' pagination-'.$arg_ref->{size} : ''; | |||
111 | 6 | 12 | my ($prev_uri, $next_uri) = $self->_prev_next_uri($arg_ref); | ||||
112 | 6 | 34 | return ' ' |
||||
113 | . '
|
||||||
114 | . $self->_pager_item($prev_uri, $arg_ref->{prev_text}) | ||||||
115 | . $pagination | ||||||
116 | . $self->_pager_item($next_uri, $arg_ref->{next_text}) | ||||||
117 | . '' | ||||||
118 | . ''; | ||||||
119 | } | ||||||
120 | |||||||
121 | sub _pagination_3 { | ||||||
122 | 4 | 4 | 5 | my ($self, $pagination, $arg_ref) = @_; | |||
123 | |||||||
124 | 4 | 100 | 11 | my $alignment = $arg_ref->{centered} | |||
100 | |||||||
125 | ? 'text-center' | ||||||
126 | : ($arg_ref->{right} ? 'text-right' : 'text-left'); | ||||||
127 | 4 | 100 | 50 | 13 | my $size = defined $arg_ref->{size} ? ({ | ||
128 | 'mini' => ' pagination-sm', | ||||||
129 | 'small' => ' pagination-sm', | ||||||
130 | 'large' => ' pagination-lg', | ||||||
131 | }->{$arg_ref->{size}} || '') : ''; | ||||||
132 | 4 | 8 | my ($prev_uri, $next_uri) = $self->_prev_next_uri($arg_ref); | ||||
133 | 4 | 14 | return ' ' |
||||
134 | . '
|
||||||
135 | . $self->_pager_item($prev_uri, $arg_ref->{prev_text}) | ||||||
136 | . $pagination | ||||||
137 | . $self->_pager_item($next_uri, $arg_ref->{next_text}) | ||||||
138 | . '' | ||||||
139 | . ''; | ||||||
140 | } | ||||||
141 | |||||||
142 | |||||||
143 | |||||||
144 | sub pager { | ||||||
145 | 5 | 5 | 1 | 521 | my ($self, $arg_ref) = @_; | ||
146 | |||||||
147 | 5 | 18 | $arg_ref = { | ||||
148 | 5 | 100 | 36 | %{$self->{default}}, | |||
149 | 5 | 6 | %{$arg_ref || {}}, | ||||
150 | }; | ||||||
151 | |||||||
152 | 5 | 12 | my $pager = $arg_ref->{pager}; | ||||
153 | 5 | 100 | 66 | 45 | unless (blessed $pager && $pager->isa('Data::Page')) { | ||
154 | 1 | 5 | $self->_throw("Required 'pager' parameter not passed or not a 'Data::Page' instance"); | ||||
155 | } | ||||||
156 | |||||||
157 | 4 | 11 | my ($prev_uri, $next_uri) = $self->_prev_next_uri($arg_ref); | ||||
158 | 3 | 100 | 35 | my $prev_page = $self->_pager_item( | |||
159 | $prev_uri, $arg_ref->{prev_text}, $arg_ref->{align} ? 'previous' : () | ||||||
160 | ); | ||||||
161 | 3 | 100 | 9 | my $next_page = $self->_pager_item( | |||
162 | $next_uri, $arg_ref->{next_text}, $arg_ref->{align} ? 'next' : () | ||||||
163 | ); | ||||||
164 | |||||||
165 | 3 | 18 | return '
|
||||
166 | . $prev_page | ||||||
167 | . $next_page | ||||||
168 | . ''; | ||||||
169 | } | ||||||
170 | |||||||
171 | |||||||
172 | sub _pager_item { | ||||||
173 | 30 | 30 | 920 | my ($self, $uri, $text, @item_classes) = @_; | |||
174 | |||||||
175 | 30 | 27 | my $content; | ||||
176 | 30 | 100 | 36 | if (defined $uri) { | |||
177 | 15 | 26 | $content = ''.$text.''; | ||||
178 | } | ||||||
179 | else { | ||||||
180 | 15 | 16 | push @item_classes, 'disabled'; | ||||
181 | 15 | 20 | $content = ''.$text.''; | ||||
182 | } | ||||||
183 | |||||||
184 | 30 | 26 | my $item = ' | ||||
185 | 30 | 100 | 49 | if (scalar @item_classes) { | |||
186 | 21 | 32 | $item .= ' class="'.join(' ', @item_classes).'"'; | ||||
187 | } | ||||||
188 | |||||||
189 | 30 | 120 | return $item.'>'.$content.''; | ||||
190 | } | ||||||
191 | |||||||
192 | |||||||
193 | sub _prev_next_uri { | ||||||
194 | 18 | 18 | 1790 | my ($self, $arg_ref) = @_; | |||
195 | |||||||
196 | 18 | 21 | my $pager = $arg_ref->{pager}; | ||||
197 | 36 | 100 | 1987 | return map { | |||
198 | 18 | 36 | $_ ? $self->_uri_for_page($_, $arg_ref) : undef; | ||||
199 | } ($pager->previous_page(), $pager->next_page()); | ||||||
200 | } | ||||||
201 | |||||||
202 | |||||||
203 | sub _uri_for_page { | ||||||
204 | 34 | 34 | 1758 | my ($self, $page, $arg_ref) = @_; | |||
205 | |||||||
206 | 34 | 48 | my $uri = $arg_ref->{uri}; | ||||
207 | 34 | 100 | 66 | 120 | if (! defined $uri || $uri eq '') { | ||
208 | 2 | 7 | $self->_throw("Required 'uri' parameter not passed"); | ||||
209 | } | ||||||
210 | 32 | 87 | $uri =~ s/__PAGE__/( $page + $arg_ref->{offset} ) * $arg_ref->{factor}/eg; | ||||
32 | 83 | ||||||
211 | 32 | 66 | return encode_entities($uri); | ||||
212 | } | ||||||
213 | |||||||
214 | |||||||
215 | sub _throw { | ||||||
216 | 4 | 4 | 8 | my ($self, $error) = @_; | |||
217 | 4 | 14 | croak(Template::Exception->new('Bootstrap.Pagination', $error)); | ||||
218 | } | ||||||
219 | |||||||
220 | |||||||
221 | 1; | ||||||
222 | |||||||
223 | |||||||
224 | __END__ |