| 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__ |