File | /wise/base/static/lib/perl5/site_perl/5.10.0/Data/Page.pm | Statements Executed | 15 | Total Time | 0.000798 seconds |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine | |
---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | Data::Page:: | BEGIN |
0 | 0 | 0 | 0 | 0 | Data::Page:: | current_page |
0 | 0 | 0 | 0 | 0 | Data::Page:: | entries_on_this_page |
0 | 0 | 0 | 0 | 0 | Data::Page:: | entries_per_page |
0 | 0 | 0 | 0 | 0 | Data::Page:: | first |
0 | 0 | 0 | 0 | 0 | Data::Page:: | first_page |
0 | 0 | 0 | 0 | 0 | Data::Page:: | last |
0 | 0 | 0 | 0 | 0 | Data::Page:: | last_page |
0 | 0 | 0 | 0 | 0 | Data::Page:: | new |
0 | 0 | 0 | 0 | 0 | Data::Page:: | next_page |
0 | 0 | 0 | 0 | 0 | Data::Page:: | previous_page |
0 | 0 | 0 | 0 | 0 | Data::Page:: | skipped |
0 | 0 | 0 | 0 | 0 | Data::Page:: | splice |
0 | 0 | 0 | 0 | 0 | Data::Page:: | total_entries |
Line | Stmts. | Exclusive Time | Avg. | Code |
---|---|---|---|---|
1 | package Data::Page; | |||
2 | 3 | 3.6e-5 | 1.2e-5 | use Carp; # spent 76µs making 1 call to Exporter::import |
3 | 3 | 2.6e-5 | 8.7e-6 | use strict; # spent 8µs making 1 call to strict::import |
4 | 3 | 5.6e-5 | 1.9e-5 | use base 'Class::Accessor::Chained::Fast'; # spent 4.91ms making 1 call to base::import, max recursion depth 1 |
5 | 1 | 2.1e-5 | 2.1e-5 | __PACKAGE__->mk_accessors(qw(total_entries entries_per_page current_page)); # spent 200µs making 1 call to Class::Accessor::mk_accessors |
6 | ||||
7 | 3 | 0.00065 | 0.00022 | use vars qw($VERSION); # spent 35µs making 1 call to vars::import |
8 | 1 | 0 | 0 | $VERSION = '2.00'; |
9 | ||||
10 | sub new { | |||
11 | my $class = shift; | |||
12 | my $self = {}; | |||
13 | bless($self, $class); | |||
14 | ||||
15 | my ($total_entries, $entries_per_page, $current_page) = @_; | |||
16 | $self->total_entries($total_entries || 0); | |||
17 | $self->entries_per_page($entries_per_page || 10); | |||
18 | $self->current_page($current_page || 1); | |||
19 | return $self; | |||
20 | } | |||
21 | ||||
22 | sub entries_per_page { | |||
23 | my $self = shift; | |||
24 | my $entries_per_page = $_[0]; | |||
25 | if (@_) { | |||
26 | croak("Fewer than one entry per page!") if $entries_per_page < 1; | |||
27 | return $self->_entries_per_page_accessor(@_); | |||
28 | } | |||
29 | return $self->_entries_per_page_accessor(); | |||
30 | } | |||
31 | ||||
32 | sub current_page { | |||
33 | my $self = shift; | |||
34 | if (@_) { | |||
35 | return $self->_current_page_accessor(@_); | |||
36 | } | |||
37 | return $self->first_page unless defined $self->_current_page_accessor; | |||
38 | return $self->first_page if $self->_current_page_accessor < $self->first_page; | |||
39 | return $self->last_page if $self->_current_page_accessor > $self->last_page; | |||
40 | return $self->_current_page_accessor(); | |||
41 | } | |||
42 | ||||
43 | sub total_entries { | |||
44 | my $self = shift; | |||
45 | if (@_) { | |||
46 | return $self->_total_entries_accessor(@_); | |||
47 | } | |||
48 | return $self->_total_entries_accessor; | |||
49 | } | |||
50 | ||||
51 | sub entries_on_this_page { | |||
52 | my $self = shift; | |||
53 | ||||
54 | if ($self->total_entries == 0) { | |||
55 | return 0; | |||
56 | } else { | |||
57 | return $self->last - $self->first + 1; | |||
58 | } | |||
59 | } | |||
60 | ||||
61 | sub first_page { | |||
62 | my $self = shift; | |||
63 | ||||
64 | return 1; | |||
65 | } | |||
66 | ||||
67 | sub last_page { | |||
68 | my $self = shift; | |||
69 | ||||
70 | my $pages = $self->total_entries / $self->entries_per_page; | |||
71 | my $last_page; | |||
72 | ||||
73 | if ($pages == int $pages) { | |||
74 | $last_page = $pages; | |||
75 | } else { | |||
76 | $last_page = 1 + int($pages); | |||
77 | } | |||
78 | ||||
79 | $last_page = 1 if $last_page < 1; | |||
80 | return $last_page; | |||
81 | } | |||
82 | ||||
83 | sub first { | |||
84 | my $self = shift; | |||
85 | ||||
86 | if ($self->total_entries == 0) { | |||
87 | return 0; | |||
88 | } else { | |||
89 | return (($self->current_page - 1) * $self->entries_per_page) + 1; | |||
90 | } | |||
91 | } | |||
92 | ||||
93 | sub last { | |||
94 | my $self = shift; | |||
95 | ||||
96 | if ($self->current_page == $self->last_page) { | |||
97 | return $self->total_entries; | |||
98 | } else { | |||
99 | return ($self->current_page * $self->entries_per_page); | |||
100 | } | |||
101 | } | |||
102 | ||||
103 | sub previous_page { | |||
104 | my $self = shift; | |||
105 | ||||
106 | if ($self->current_page > 1) { | |||
107 | return $self->current_page - 1; | |||
108 | } else { | |||
109 | return undef; | |||
110 | } | |||
111 | } | |||
112 | ||||
113 | sub next_page { | |||
114 | my $self = shift; | |||
115 | ||||
116 | $self->current_page < $self->last_page ? $self->current_page + 1 : undef; | |||
117 | } | |||
118 | ||||
119 | # This method would probably be better named 'select' or 'slice' or | |||
120 | # something, because it doesn't modify the array the way | |||
121 | # CORE::splice() does. | |||
122 | sub splice { | |||
123 | my ($self, $array) = @_; | |||
124 | my $top = @$array > $self->last ? $self->last : @$array; | |||
125 | return () if $top == 0; # empty | |||
126 | return @{$array}[ $self->first - 1 .. $top - 1 ]; | |||
127 | } | |||
128 | ||||
129 | sub skipped { | |||
130 | my $self = shift; | |||
131 | ||||
132 | my $skipped = $self->first - 1; | |||
133 | return 0 if $skipped < 0; | |||
134 | return $skipped; | |||
135 | } | |||
136 | ||||
137 | 1 | 4.0e-6 | 4.0e-6 | 1; |
138 | ||||
139 | __END__ | |||
140 | ||||
141 | =head1 NAME | |||
142 | ||||
143 | Data::Page - help when paging through sets of results | |||
144 | ||||
145 | =head1 SYNOPSIS | |||
146 | ||||
147 | use Data::Page; | |||
148 | ||||
149 | my $page = Data::Page->new(); | |||
150 | $page->total_entries($total_entries); | |||
151 | $page->entries_per_page($entries_per_page); | |||
152 | $page->current_page($current_page); | |||
153 | ||||
154 | print " First page: ", $page->first_page, "\n"; | |||
155 | print " Last page: ", $page->last_page, "\n"; | |||
156 | print "First entry on page: ", $page->first, "\n"; | |||
157 | print " Last entry on page: ", $page->last, "\n"; | |||
158 | ||||
159 | =head1 DESCRIPTION | |||
160 | ||||
161 | When searching through large amounts of data, it is often the case | |||
162 | that a result set is returned that is larger than we want to display | |||
163 | on one page. This results in wanting to page through various pages of | |||
164 | data. The maths behind this is unfortunately fiddly, hence this | |||
165 | module. | |||
166 | ||||
167 | The main concept is that you pass in the number of total entries, the | |||
168 | number of entries per page, and the current page number. You can then | |||
169 | call methods to find out how many pages of information there are, and | |||
170 | what number the first and last entries on the current page really are. | |||
171 | ||||
172 | For example, say we wished to page through the integers from 1 to 100 | |||
173 | with 20 entries per page. The first page would consist of 1-20, the | |||
174 | second page from 21-40, the third page from 41-60, the fourth page | |||
175 | from 61-80 and the fifth page from 81-100. This module would help you | |||
176 | work this out. | |||
177 | ||||
178 | =head1 METHODS | |||
179 | ||||
180 | =head2 new | |||
181 | ||||
182 | This is the constructor, which takes no arguments. | |||
183 | ||||
184 | my $page = Data::Page->new(); | |||
185 | ||||
186 | There is also an old, deprecated constructor, which currently takes | |||
187 | two mandatory arguments, the total number of entries and the number of | |||
188 | entries per page. It also optionally takes the current page number: | |||
189 | ||||
190 | my $page = Data::Page->new($total_entries, $entries_per_page, $current_page); | |||
191 | ||||
192 | =head2 total_entries | |||
193 | ||||
194 | This method get or sets the total number of entries: | |||
195 | ||||
196 | print "Entries:", $page->total_entries, "\n"; | |||
197 | ||||
198 | =head2 entries_per_page | |||
199 | ||||
200 | This method gets or sets the total number of entries per page (which | |||
201 | defaults to 10): | |||
202 | ||||
203 | print "Per page:", $page->entries_per_page, "\n"; | |||
204 | ||||
205 | =head2 current_page | |||
206 | ||||
207 | This method gets or sets the current page number (which defaults to 1): | |||
208 | ||||
209 | print "Page: ", $page->current_page, "\n"; | |||
210 | ||||
211 | =head2 entries_on_this_page | |||
212 | ||||
213 | This methods returns the number of entries on the current page: | |||
214 | ||||
215 | print "There are ", $page->entries_on_this_page, " entries displayed\n"; | |||
216 | ||||
217 | =head2 first_page | |||
218 | ||||
219 | This method returns the first page. This is put in for reasons of | |||
220 | symmetry with last_page, as it always returns 1: | |||
221 | ||||
222 | print "Pages range from: ", $page->first_page, "\n"; | |||
223 | ||||
224 | =head2 last_page | |||
225 | ||||
226 | This method returns the total number of pages of information: | |||
227 | ||||
228 | print "Pages range to: ", $page->last_page, "\n"; | |||
229 | ||||
230 | =head2 first | |||
231 | ||||
232 | This method returns the number of the first entry on the current page: | |||
233 | ||||
234 | print "Showing entries from: ", $page->first, "\n"; | |||
235 | ||||
236 | =head2 last | |||
237 | ||||
238 | This method returns the number of the last entry on the current page: | |||
239 | ||||
240 | print "Showing entries to: ", $page->last, "\n"; | |||
241 | ||||
242 | =head2 previous_page | |||
243 | ||||
244 | This method returns the previous page number, if one exists. Otherwise | |||
245 | it returns undefined: | |||
246 | ||||
247 | if ($page->previous_page) { | |||
248 | print "Previous page number: ", $page->previous_page, "\n"; | |||
249 | } | |||
250 | ||||
251 | =head2 next_page | |||
252 | ||||
253 | This method returns the next page number, if one exists. Otherwise | |||
254 | it returns undefined: | |||
255 | ||||
256 | if ($page->next_page) { | |||
257 | print "Next page number: ", $page->next_page, "\n"; | |||
258 | } | |||
259 | ||||
260 | =head2 splice | |||
261 | ||||
262 | This method takes in a listref, and returns only the values which are | |||
263 | on the current page: | |||
264 | ||||
265 | @visible_holidays = $page->splice(\@holidays); | |||
266 | ||||
267 | =head2 skipped | |||
268 | ||||
269 | This method is useful paging through data in a database using SQL | |||
270 | LIMIT clauses. It is simply $page->first - 1: | |||
271 | ||||
272 | $sth = $dbh->prepare( | |||
273 | q{SELECT * FROM table ORDER BY rec_date LIMIT ?, ?} | |||
274 | ); | |||
275 | $sth->execute($date, $page->skipped, $page->entries_per_page); | |||
276 | ||||
277 | =head1 NOTES | |||
278 | ||||
279 | It has been said before that this code is "too simple" for CPAN, but I | |||
280 | must disagree. I have seen people write this kind of code over and | |||
281 | over again and they always get it wrong. Perhaps now they will spend | |||
282 | more time getting the rest of their code right... | |||
283 | ||||
284 | =head1 SEE ALSO | |||
285 | ||||
286 | Related modules which may be of interest: L<Data::Pageset>, | |||
287 | L<Data::Page::Tied>, L<Data::SpreadPagination>. | |||
288 | ||||
289 | =head1 AUTHOR | |||
290 | ||||
291 | Based on code originally by Leo Lapworth, with many changes added by | |||
292 | by Leon Brocard <acme@astray.com>. | |||
293 | ||||
294 | =head1 COPYRIGHT | |||
295 | ||||
296 | Copyright (C) 2000-4, Leon Brocard | |||
297 | ||||
298 | This module is free software; you can redistribute it or modify it | |||
299 | under the same terms as Perl itself. | |||
300 | ||||
301 |