File Coverage

blib/lib/Template/Plugin/Bootstrap/Pagination.pm
Criterion Covered Total %
statement 90 91 98.9
branch 35 36 97.2
condition 21 26 80.7
subroutine 15 15 100.0
pod 3 3 100.0
total 164 171 95.9


line stmt bran cond sub pod time code
1             package Template::Plugin::Bootstrap::Pagination;
2             {
3             $Template::Plugin::Bootstrap::Pagination::VERSION = '0.001002';
4             }
5 1     1   65016 use parent qw(Template::Plugin);
  1         255  
  1         6  
6              
7             # ABSTRACT: Produce HTML suitable for the Bootstrap pagination component
8              
9 1     1   1257 use strict;
  1         1  
  1         27  
10 1     1   4 use warnings;
  1         1  
  1         24  
11              
12 1     1   5 use Carp;
  1         1  
  1         88  
13 1     1   701 use MRO::Compat;
  1         3075  
  1         24  
14 1     1   847 use HTML::Entities;
  1         7215  
  1         126  
15 1     1   8 use Scalar::Util qw(blessed);
  1         2  
  1         49  
16 1     1   6 use Template::Exception;
  1         2  
  1         891  
17              
18              
19             sub new {
20 9     9 1 102541 my ($class, $context, $arg_ref) = @_;
21              
22 9         76 my $self = $class->next::method($context, $arg_ref);
23              
24 9 50 66     270 if (defined $arg_ref && ref $arg_ref ne 'HASH') {
25 0         0 $self->_throw('Hash reference required');
26             }
27 9   100     53 $arg_ref ||= {};
28 9         95 $self->{default} = {
29             prev_text => '«',
30             next_text => '»',
31             centered => 0,
32             right => 0,
33             siblings => 3,
34             offset => 0,
35             factor => 1,
36 9         22 %{$arg_ref},
37             };
38              
39 9         37 return $self;
40             }
41              
42              
43              
44             sub pagination {
45 7     7 1 1665 my ($self, $arg_ref) = @_;
46              
47 7         26 $arg_ref = {
48 7 100       60 %{$self->{default}},
49 7         9 %{$arg_ref || {}},
50             };
51              
52 7         23 my $pager = $arg_ref->{pager};
53 7 100 66     80 unless (blessed $pager && $pager->isa('Data::Page')) {
54 1         4 $self->_throw("Required 'pager' parameter not passed or not a 'Data::Page' instance");
55             }
56              
57 6         13 my $pagination = '';
58 6 100       19 if ($pager->total_entries() > $pager->entries_per_page()) {
59 4         94 my $current_page = $pager->current_page();
60 4         191 my $first_page = $pager->first_page();
61 4         22 my $last_page = $pager->last_page();
62 4         81 my $page = $first_page;
63 4         12 PAGE: while ($page <= $last_page) {
64 18 100       43 if ($current_page == $page) {
65 4         12 $pagination .= '
  • '
  • 66             . ''.$page.''
    67             . '';
    68             }
    69             else {
    70 14 100 100     140 if ($page == $first_page || $page == $last_page
        100 100        
          66        
          100        
    71             || abs($page - $current_page) <= ($arg_ref->{siblings})
    72             || $last_page <= (2 * $arg_ref->{siblings} + 1)) {
    73 10         28 $pagination .= '
  • '
  • 74             . ''.$page.''
    75             . '';
    76             }
    77             elsif ($first_page + 1 == $page || $last_page - 1 == $page) {
    78 2         5 $pagination .= '
  • '
  • 79             . ''
    80             . '';
    81             }
    82             else {
    83 2 100       7 $page = ($page < $current_page)
    84             ? $current_page - $arg_ref->{siblings}
    85             : $last_page - 1;
    86 2         7 next PAGE;
    87             }
    88             }
    89 15         174 $page++;
    90             }
    91             }
    92              
    93 5 100       77 my $alignment = $arg_ref->{centered}
        100          
    94             ? ' pagination-centered'
    95             : ($arg_ref->{right} ? ' pagination-right' : '');
    96 5         16 my ($prev_uri, $next_uri) = $self->_prev_next_uri($arg_ref);
    97 5         49 return '
    '
    98             . '
      '
    99             . $self->_pager_item($prev_uri, $arg_ref->{prev_text})
    100             . $pagination
    101             . $self->_pager_item($next_uri, $arg_ref->{next_text})
    102             . ''
    103             . '';
    104             }
    105              
    106              
    107              
    108             sub pager {
    109 5     5 1 757 my ($self, $arg_ref) = @_;
    110              
    111 5         23 $arg_ref = {
    112 5 100       45 %{$self->{default}},
    113 5         7 %{$arg_ref || {}},
    114             };
    115              
    116 5         16 my $pager = $arg_ref->{pager};
    117 5 100 66     94 unless (blessed $pager && $pager->isa('Data::Page')) {
    118 1         16 $self->_throw("Required 'pager' parameter not passed or not a 'Data::Page' instance");
    119             }
    120              
    121 4         23 my ($prev_uri, $next_uri) = $self->_prev_next_uri($arg_ref);
    122 3 100       64 my $prev_page = $self->_pager_item(
    123             $prev_uri, $arg_ref->{prev_text}, $arg_ref->{align} ? 'previous' : ()
    124             );
    125 3 100       14 my $next_page = $self->_pager_item(
    126             $next_uri, $arg_ref->{next_text}, $arg_ref->{align} ? 'next' : ()
    127             );
    128              
    129 3         27 return '
      '
    130             . $prev_page
    131             . $next_page
    132             . '';
    133             }
    134              
    135              
    136             sub _pager_item {
    137 20     20   3757 my ($self, $uri, $text, @item_classes) = @_;
    138              
    139 20         29 my $content;
    140 20 100       125 if (defined $uri) {
    141 14         55 $content = ''.$text.'';
    142             }
    143             else {
    144 6         11 push @item_classes, 'disabled';
    145 6         14 $content = ''.$text.'';
    146             }
    147              
    148 20         29 my $item = '
    149 20 100       56 if (scalar @item_classes) {
    150 12         36 $item .= ' class="'.join(' ', @item_classes).'"';
    151             }
    152              
    153 20         129 return $item.'>'.$content.'';
    154             }
    155              
    156              
    157             sub _prev_next_uri {
    158 13     13   3509 my ($self, $arg_ref) = @_;
    159              
    160 13         22 my $pager = $arg_ref->{pager};
    161 26 100       2546 return map {
    162 13         52 $_ ? $self->_uri_for_page($_, $arg_ref) : undef;
    163             } ($pager->previous_page(), $pager->next_page());
    164             }
    165              
    166              
    167             sub _uri_for_page {
    168 32     32   2704 my ($self, $page, $arg_ref) = @_;
    169              
    170 32         57 my $uri = $arg_ref->{uri};
    171 32 100 66     436 if (! defined $uri || $uri eq '') {
    172 2         7 $self->_throw("Required 'uri' parameter not passed");
    173             }
    174 30         117 $uri =~ s/__PAGE__/( $page + $arg_ref->{offset} ) * $arg_ref->{factor}/eg;
      30         114  
    175 30         92 return encode_entities($uri);
    176             }
    177              
    178              
    179             sub _throw {
    180 4     4   9 my ($self, $error) = @_;
    181 4         25 croak(Template::Exception->new('Bootstrap.Pagination', $error));
    182             }
    183              
    184              
    185             1;
    186              
    187              
    188             __END__