File Coverage

blib/lib/Data/Pageset/Exponential.pm
Criterion Covered Total %
statement 103 103 100.0
branch 21 22 95.4
condition n/a
subroutine 28 28 100.0
pod 9 12 75.0
total 161 165 97.5


line stmt bran cond sub pod time code
1             package Data::Pageset::Exponential;
2              
3             # ABSTRACT: Page numbering for very large page numbers
4              
5 3     3   2311 use v5.10.1;
  3         10  
6              
7 3     3   1598 use Moo;
  3         34707  
  3         14  
8              
9 3     3   4541 use List::Util 1.33 qw/ all min /;
  3         71  
  3         301  
10 3     3   1371 use PerlX::Maybe;
  3         7389  
  3         13  
11 3     3   1635 use POSIX qw/ ceil floor /;
  3         19576  
  3         18  
12 3     3   5810 use MooX::Aliases;
  3         16080  
  3         19  
13 3     3   2419 use MooX::TypeTiny;
  3         594  
  3         16  
14 3     3   102697 use Types::Common::Numeric qw/ PositiveOrZeroInt PositiveInt /;
  3         288254  
  3         37  
15 3     3   1890 use Types::Standard qw/ is_Int Int ArrayRef is_HashRef /;
  3         7  
  3         19  
16              
17              
18 3     3   4554 use asa 'Data::Page';
  3         809  
  3         20  
19              
20 3     3   1683 use namespace::autoclean;
  3         41090  
  3         16  
21              
22             # RECOMMEND PREREQ: Type::Tiny::XS
23             # RECOMMEND PREREQ: Ref::Util::XS
24              
25             our $VERSION = 'v0.3.1';
26              
27              
28             has total_entries => (
29             is => 'rw',
30             isa => PositiveOrZeroInt,
31             default => 0,
32             );
33              
34              
35             has entries_per_page => (
36             is => 'rw',
37             isa => PositiveInt,
38             default => 10,
39             );
40              
41              
42             has first_page => (
43             is => 'ro',
44             isa => Int,
45             default => 1,
46             );
47              
48              
49             has current_page => (
50             is => 'rw',
51             isa => Int,
52             lazy => 1,
53             default => \&first_page,
54             coerce => sub { floor( $_[0] // 0 ) },
55             );
56              
57              
58             has exponent_base => (
59             is => 'ro',
60             isa => PositiveInt,
61             default => 10,
62             );
63              
64              
65             has exponent_max => (
66             is => 'ro',
67             isa => PositiveInt,
68             default => 3,
69             );
70              
71              
72             has pages_per_exponent => (
73             is => 'ro',
74             isa => PositiveInt,
75             default => 3,
76             );
77              
78              
79             has pages_per_set => (
80             is => 'lazy',
81             isa => PositiveInt,
82             alias => 'max_pages_per_set',
83             builder => sub {
84 1     1   871 my ($self) = @_;
85 3     3   2341 use integer;
  3         47  
  3         65  
86 1         8 my $n = $self->pages_per_exponent * ( $self->exponent_max + 1 );
87 1         18 return ($n - 1) * 2 + 1;
88             },
89             );
90              
91              
92             has series => (
93             is => 'lazy',
94             isa => ArrayRef [Int],
95             builder => sub {
96 1     1   14 my ($self) = @_;
97              
98 3     3   308 use integer;
  3         28  
  3         13  
99              
100 1         17 my @series;
101              
102 1         7 my $n = $self->exponent_base;
103 1         4 my $m = $self->exponent_max;
104              
105 1         3 my $j = 0;
106 1         5 while ( $j <= $m ) {
107              
108 4         8 my $i = $n**$j;
109 4         5 my $a = $i;
110 4         11 my $p = $self->pages_per_exponent;
111              
112 4         12 while ( $p-- ) {
113 12         18 push @series, $a - 1;
114 12         25 $a += $i;
115             }
116              
117 4         18 $j++;
118              
119             }
120              
121 1         6 my @prevs = map { -$_ } reverse @series[1..$#series];
  11         27  
122              
123              
124 1         25 return [@prevs, @series];
125             },
126             );
127              
128             around current_page => sub {
129             my $next = shift;
130             my $self = shift;
131              
132             # N.B. unlike Data::Page, setting a value outside the first_page
133             # or last_page will not return that value.
134              
135             my $page = $self->$next(@_);
136              
137             return $self->first_page if $page < $self->first_page;
138              
139             return $self->last_page if $page > $self->last_page;
140              
141             return $page;
142             };
143              
144              
145             sub entries_on_this_page {
146 71     71 1 39720 my ($self) = @_;
147              
148 71 100       1732 if ( $self->total_entries ) {
149 68         543 return $self->last - $self->first + 1;
150             }
151             else {
152 3         34 return 0;
153             }
154             }
155              
156              
157             sub last_page {
158 1558     1558 1 75150 my ($self) = @_;
159 1558 100       25214 return $self->total_entries
160             ? ceil( $self->total_entries / $self->entries_per_page )
161             : $self->first_page;
162             }
163              
164              
165             sub first {
166 386     386 1 39011 my ($self) = @_;
167 386 100       6820 if ( $self->total_entries ) {
168 380         8608 return ( $self->current_page - 1 ) * $self->entries_per_page + 1;
169             }
170             else {
171 6         58 return 0;
172             }
173             }
174              
175              
176             sub last {
177 211     211 1 37188 my ($self) = @_;
178 211 100       5107 if ( $self->current_page == $self->last_page ) {
179 121         2967 return $self->total_entries;
180             }
181             else {
182 90         2314 return $self->current_page * $self->entries_per_page;
183             }
184             }
185              
186              
187             sub previous_page {
188 71     71 1 38648 my ($self) = @_;
189 71         1881 my $page = $self->current_page;
190              
191 71 100       461 return $page > $self->first_page
192             ? $page - 1
193             : undef;
194             }
195              
196              
197             sub next_page {
198 71     71 1 171 my ($self) = @_;
199 71         1813 my $page = $self->current_page;
200              
201 71 100       166 return $page < $self->last_page
202             ? $page + 1
203             : undef;
204             }
205              
206              
207             sub splice {
208 72     72 0 654 my ( $self, $items ) = @_;
209              
210 72         182 my $last = min( $self->last, scalar(@$items) );
211              
212             return $last
213 72 100       754 ? @{$items}[ $self->first - 1 .. $last - 1 ]
  68         720  
214             : ();
215             }
216              
217              
218             sub skipped {
219 71     71 0 37973 my ($self) = @_;
220 71 100       1682 return $self->total_entries
221             ? $self->first - 1
222             : 0;
223             }
224              
225             # Ideally, we'd use a trigger instead, but Moo does not pass the old
226             # value to a trigger.
227              
228             around entries_per_page => sub {
229             my $next = shift;
230             my $self = shift;
231              
232             if (@_) {
233              
234             my $value = shift;
235              
236             my $first = $self->first;
237              
238             $self->$next($value);
239              
240             $self->current_page( $self->first_page + $first / $value );
241              
242             return $value;
243             }
244             else {
245              
246             return $self->$next;
247              
248             }
249             };
250              
251              
252             sub pages_in_set {
253 2     2 1 545 my ($self) = @_;
254              
255 3     3   2977 use integer;
  3         8  
  3         14  
256              
257 2         8 my $first = $self->first_page;
258 2         5 my $last = $self->last_page;
259 2         52 my $page = $self->current_page;
260              
261             return [
262 46 100       151 grep { $first <= $_ && $_ <= $last }
263 2         4 map { $page + $_ } @{ $self->series }
  46         95  
  2         67  
264             ];
265             }
266              
267              
268             sub previous_set {
269 2     2 1 5 my ($self) = @_;
270              
271 2         53 my $page = $self->current_page - (2 * $self->pages_per_exponent) - 1;
272 2 100       15 return $page < $self->first_page
273             ? undef
274             : $page;
275             }
276              
277              
278             sub next_set {
279 2     2 1 6 my ($self) = @_;
280              
281 2         53 my $page = $self->current_page + (2 * $self->pages_per_exponent) - 1;
282 2 50       6 return $page > $self->last_page
283             ? undef
284             : $page;
285             }
286              
287              
288             sub change_entries_per_page {
289 70     70 0 37309 my ($self, $value) = @_;
290              
291 70         1828 $self->entries_per_page($value);
292              
293 70         1288 return $self->current_page;
294             }
295              
296              
297             sub BUILDARGS {
298             my ( $class, @args ) = @_;
299              
300             if (@args == 1 && is_HashRef(@args)) {
301             return $args[0];
302             }
303              
304             if ( @args && ( @args <= 3 ) && all { is_Int($_) } @args ) {
305              
306             return {
307             total_entries => $args[0],
308             maybe entries_per_page => $args[1],
309             maybe current_page => $args[2],
310             };
311              
312             }
313              
314             return {@args};
315             }
316              
317              
318             1;
319              
320             __END__