File Coverage

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__