File Coverage

blib/lib/Catmandu/Paged.pm
Criterion Covered Total %
statement 81 92 88.0
branch 49 68 72.0
condition 5 9 55.5
subroutine 17 18 94.4
pod 9 10 90.0
total 161 197 81.7


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 19     19   100180  
  19         102  
  19         266  
4             our $VERSION = '1.2019';
5              
6             use Moo::Role;
7 19     19   355 use namespace::clean;
  19         45  
  19         116  
8 19     19   6812  
  19         56  
  19         140  
9             requires 'start';
10             requires 'limit';
11             requires 'total';
12             requires 'maximum_offset';
13              
14             has max_pages_in_spread => (is => 'rw', lazy => 1, default => sub {5});
15              
16             # function _do_pagination copied from Data::SpreadPagination,
17             # decrease dependencies for Catmandu
18              
19             my $x = shift;
20             return int($x + 0.9999999);
21 62     62   120 }
22 62         196  
23             my $x = shift;
24             return int $x;
25             }
26 4     4   6  
27 4         11 my $x = shift;
28             return int($x + 0.5);
29             }
30              
31 6     6   6 my $self = $_[0];
32 6         12 my $total = $self->total;
33             if (my $max_offset = $self->maximum_offset) {
34             $total = $max_offset + 1 if $total > $max_offset;
35             }
36 36     36   48 $total;
37 36         62 }
38 36 100       95  
39 4 50       16 my $self = shift;
40             my $total = $self->_capped_total;
41 36         113 my $per_page = $self->limit;
42             my $current_page = $self->page;
43             my $max_pages = $self->max_pages_in_spread;
44              
45 4     4   5 # qNsizes
46 4         6 my @q_size = ();
47 4         6 my ($add_pages, $adj);
48 4         13  
49 4         89 # step 2
50             my $total_pages = _ceil($total / $per_page);
51             my $visible_pages
52 4         7 = $max_pages < ($total_pages - 1) ? $max_pages : $total_pages - 1;
53 4         6 if ($total_pages - 1 <= $max_pages) {
54             @q_size = ($current_page - 1, 0, 0, $total_pages - $current_page);
55             }
56 4         10 else {
57 4 100       10 @q_size = (
58             _floor($visible_pages / 4),
59 4 100       8 _round($visible_pages / 4),
60 2         5 _ceil($visible_pages / 4),
61             _round(($visible_pages - _round($visible_pages / 4)) / 3)
62             );
63 2         7 if ($current_page - $q_size[0] < 1) {
64             $add_pages = $q_size[0] + $q_size[1] - $current_page + 1;
65             @q_size = (
66             $current_page - 1,
67             0,
68             $q_size[2] + _ceil($add_pages / 2),
69 2 100       8 $q_size[3] + _floor($add_pages / 2)
    50          
    0          
    0          
70 1         2 );
71 1         4 }
72             elsif (
73             $current_page - $q_size[1] - _ceil($q_size[1] / 3) <= $q_size[0])
74             {
75             $adj = _ceil((3 * ($current_page - $q_size[0] - 1)) / 4);
76             $add_pages = $q_size[1] - $adj;
77             @q_size = (
78             $q_size[0], $adj,
79             $q_size[2] + _ceil($add_pages / 2),
80             $q_size[3] + _floor($add_pages / 2)
81 1         5 );
82 1         3 }
83 1         3 elsif ($current_page + $q_size[3] >= $total_pages) {
84             $add_pages
85             = $q_size[2] + $q_size[3] - $total_pages + $current_page;
86             @q_size = (
87             $q_size[0] + _floor($add_pages / 2),
88             $q_size[1] + _ceil($add_pages / 2),
89             0, $total_pages - $current_page
90 0         0 );
91             }
92 0         0 elsif ($current_page + $q_size[2] >= $total_pages - $q_size[3]) {
93             $adj = _ceil(
94             (3 * ($total_pages - $current_page - $q_size[3])) / 4);
95             $add_pages = $q_size[2] - $adj;
96             @q_size = (
97             $q_size[0] + _floor($add_pages / 2),
98             $q_size[1] + _ceil($add_pages / 2),
99 0         0 $adj, $q_size[3]
100             );
101 0         0 }
102 0         0 }
103              
104             # step 3 (PROFIT)
105             $self->{PAGE_RANGES} = [
106             $q_size[0] == 0 ? undef : [1, $q_size[0]],
107             $q_size[1] == 0 ? undef
108             : [$current_page - $q_size[1], $current_page - 1],
109             $q_size[2] == 0 ? undef
110             : [$current_page + 1, $current_page + $q_size[2]],
111             $q_size[3] == 0 ? undef
112 4 100       22 : [$total_pages - $q_size[3] + 1, $total_pages],
    50          
    100          
    50          
113             ];
114              
115             }
116              
117             my $self = shift;
118              
119             return if $self->limit < 1;
120              
121             return 1;
122             }
123              
124 5     5 1 19471 my $self = shift;
125              
126 5 100       14 return if $self->limit < 1;
127              
128 4         26 my $last = $self->_capped_total / $self->limit;
129             return _ceil($last);
130             }
131              
132 33     33 1 2561 my $self = shift;
133              
134 33 100       52 return if $self->limit < 1;
135              
136 32         97 ($self->start == 0) && (return 1);
137 32         83  
138             my $page = _ceil(($self->start + 1) / $self->limit);
139             ($page < $self->last_page) ? (return $page) : (return $self->last_page);
140             }
141 42     42 1 951  
142             my $self = shift;
143 42 100       67  
144             return if $self->limit < 1;
145 40 100       127  
146             ($self->page > 1) ? (return $self->page - 1) : (return undef);
147 20         85 }
148 20 50       32  
149             my $self = shift;
150              
151             return if $self->limit < 1;
152 5     5 1 11  
153             ($self->page < $self->last_page)
154 5 100       11 ? (return $self->page + 1)
155             : (return undef);
156 4 100       18 }
157              
158             my $self = shift;
159              
160 5     5 1 10 return 0 if $self->limit < 1 || $self->total == 0;
161              
162 5 100       9 return (($self->page - 1) * $self->limit) + 1;
163             }
164 4 50       17  
165             my $self = shift;
166              
167             return 0 if $self->limit < 1;
168              
169             ($self->page == $self->last_page)
170 5     5 1 3184 ? (return $self->_capped_total)
171             : (return ($self->page * $self->limit));
172 5 100 66     14 }
173              
174 4         33 my $self = shift;
175             return $self->limit;
176             }
177              
178 5     5 0 2476 my $self = shift;
179              
180 5 100       11 return if $self->limit < 1;
181              
182 4 50       18 $self->_do_pagination;
183             return @{$self->{PAGE_RANGES}};
184             }
185              
186             my $self = shift;
187              
188 5     5 1 11 return [] if $self->limit < 1;
189 5         12  
190             $self->_do_pagination;
191             my $ranges = $self->{PAGE_RANGES};
192             my $pages = [];
193 0     0 1 0  
194             if (!defined $ranges->[0]) {
195 0 0       0 push @$pages, undef if $self->page > 1;
196             }
197 0         0 else {
198 0         0 push @$pages, $ranges->[0][0] .. $ranges->[0][1];
  0         0  
199             push @$pages, undef
200             if defined $ranges->[1]
201             and ($ranges->[1][0] - $ranges->[0][1]) > 1;
202 5     5 1 6 }
203              
204 5 100       11 push @$pages, $ranges->[1][0] .. $ranges->[1][1] if defined $ranges->[1];
205             push @$pages, $self->page;
206 4         26 push @$pages, $ranges->[2][0] .. $ranges->[2][1] if defined $ranges->[2];
207 4         6  
208 4         6 if (!defined $ranges->[3]) {
209             push @$pages, undef if $self->page < $self->last_page;
210 4 100       8 }
211 3 50       6 else {
212             push @$pages, undef
213             if defined $ranges->[2]
214 1         4 and ($ranges->[3][0] - $ranges->[2][1]) > 1;
215 1 50 33     3 push @$pages, $ranges->[3][0] .. $ranges->[3][1];
216             }
217              
218             return $pages;
219             }
220 4 50       13  
221 4         7 1;
222 4 100       20  
223              
224 4 50       7 =pod
225 0 0       0  
226             =head1 NAME
227              
228 4 100 66     14 Catmandu::Paged - Base class for packages that need paging result sets
229              
230             =head1 SYNOPSIS
231 4         19  
232             # Create a package that needs page calculation
233             package MyPackage;
234 4         22  
235             use Moo;
236              
237             with 'Catmandu::Paged';
238              
239             sub start {
240             12; # Starting result
241             }
242              
243             sub limit {
244             10; # Number of results per page
245             }
246              
247             sub total {
248             131237128371; # Total number of results;
249             }
250              
251             package main;
252              
253             my $x = MyPackage->new;
254              
255             printf "Start page: %s\n" , $x->first_page;
256             printf "Last page: %s\n" , $x->last_page;
257             printf "Current page: %s\n" , $x->page;
258             printf "Next page: %s\n" , $x->next_page;
259              
260             =head1 DESCRIPTION
261              
262             Packages that use L<Catmandu::Paged> as base class and implement the methods
263             C<start>, C<limit> and C<total> get for free methods that can be used to do
264             page calculation.
265              
266             =head1 OVERWRITE METHODS
267              
268             =over 4
269              
270             =item start()
271              
272             Returns the index of the first item in a result page.
273              
274             =item limit()
275              
276             Returns the number of results in a page.
277              
278             =item total()
279              
280             Returns the total number of search results.
281              
282             =back
283              
284             =head1 INSTANCE METHODS
285              
286             =over 4
287              
288             =item first_page
289              
290             Returns the index the first page in a search result containing 0 or more pages.
291              
292             =item last_page
293              
294             Returns the index of the last page in a search result containing 0 or more pages.
295              
296             =item page_size
297              
298             Returns the number items on the current page.
299              
300             =item page
301              
302             Returns the current page index.
303              
304             =item previous_page
305              
306             Returns the previous page index.
307              
308             =item next_page
309              
310             Returns the next page index.
311              
312             =item first_on_page
313              
314             Returns the result index of the first result on the page.
315              
316             =item page_ranges
317              
318             =item pages_in_spread
319              
320             Returns the previous pages and next pages, depending on the current position
321             in the result set.
322              
323             =back
324              
325             =head1 SEE ALSO
326              
327             L<Catmandu::Hits>
328              
329             =cut