File Coverage

blib/lib/Mewsoft/Pagination.pm
Criterion Covered Total %
statement 3 146 2.0
branch 0 78 0.0
condition 0 3 0.0
subroutine 1 23 4.3
pod 19 19 100.0
total 23 269 8.5


line stmt bran cond sub pod time code
1             #=Copyright Infomation
2             #==========================================================
3             #Module Name : Mewsoft::Pagination
4             #Program Author : Dr. Ahmed Amin Elsheshtawy, Ph.D. Physics
5             #Home Page : http://www.mewsoft.com
6             #Contact Email : support@mewsoft.com
7             #Products : Auction, Classifieds, Directory, PPC, Forums, Snapshotter
8             #Copyrights © 2008 Mewsoft Corp. All rights reserved.
9             #==========================================================
10             #==========================================================
11             package Mewsoft::Pagination;
12              
13             # pagination - pag·i·na·tion
14             #1. the process of numbering the pages of a book.
15             #2. the number and arrangement of pages, as might be noted in a bookseller’s catalogue.
16              
17             $VERSION = '0.40';
18              
19 1     1   24382 use strict;
  1         2  
  1         2391  
20              
21             =head1 NAME
22              
23             Mewsoft::Pagination - Standalone Object-Oriented Efficient Data Pagination
24              
25             =head1 SYNOPSIS
26              
27             use Mewsoft::Pagination;
28            
29             #Example data
30             my $total_entries = 100;
31             my $entries_per_page = 10;
32             my $pages_per_set = 7;
33             my $current_page = 4;
34              
35             my $paginate = Mewsoft::Pagination->new(
36             total_entries => $total_entries,
37             entries_per_page => $entries_per_page,
38             current_page => $current_page,
39             pages_per_set => $pages_per_set,
40             mode => "slide", #modes are 'slide', 'fixed', default is 'slide'
41             );
42              
43             # General page information
44             print " First page: ", $paginate->first_page, "\n";
45             print " Last page: ", $paginate->last_page, "\n";
46             print " Next page: ", $paginate->next_page, "\n";
47             print " Previous page: ", $paginate->previous_page, "\n";
48             print " Current page: ", $paginate->current_page, "\n";
49              
50             # Entries on current page
51             print "First entry on current page: ", $paginate->first, "\n";
52             print " Last entry on current page: ", $paginate->last, "\n";
53              
54             #Returns the number of entries on the current page
55             print "Entries on the current page: ", $paginate->entries_on_current_page, " \n";
56              
57             # Page set information
58             print "First page of previous page set: ", $paginate->previous_set, "\n";
59             print " First page of next page set: ", $paginate->next_set, "\n";
60            
61             # Print the page numbers of the current set (visible pages)
62             foreach my $page (@{$paginate->pages_in_set()}) {
63             if($page == $paginate->current_page()) {
64             print "$page ";
65             } else {
66             print "$page ";
67             }
68             }
69            
70             #This will print out these results:
71             #First page: 1
72             #Last page: 10
73             #Next page: 5
74             #Previous page: 3
75             #Current page: 4
76             #First entry on current page: 31
77             #Last entry on current page: 40
78             #Entries on the current page: 10
79             #First page of previous page set:
80             #First page of next page set: 11
81             # 1 2 3 4 5 6 7
82              
83              
84             =head1 DESCRIPTION
85              
86             The standalone object-orinated module produced by Mewsoft::Pagination which
87             does not depend on any other modules can be used to create page
88             navigation for any type of applications specially good for web applications. For example
89             I use it in our Forums software, Auctions, Classifieds, and also our Directory
90             Software andmany others. It makes live easier better than repeating the same code in your applications.
91              
92             In addition it also provides methods for dealing with set of pages,
93             so that if there are too many pages you can easily break them
94             into chunks for the user to browse through. This part taken direct
95             from the similar module B. Basically this module
96             is a duplicate of the module B. The reason I created
97             this module is that all other pagination modules depends on other
98             modules which is also dependes on others modules. So it is not good
99             if you are building a large web application to ask your customers to
100             install such a small module to support your product.
101              
102             This module is very friendly where you can change any single
103             input parameter at anytime and it will automatically recalculate
104             all internal methods data without the need to recreate the object again.
105              
106             All the main object input options can be set direct and the module
107             will redo the calculations including the mode method.
108              
109             You can include this module with your applications by extracting the
110             module package and copying the module file Pagination.pm to your
111             application folder and just replace this line in the above code:
112              
113             B
114              
115             by this line:
116              
117             B
118              
119             You can even choose to view page numbers in your set in a 'sliding' fassion.
120              
121             =head1 METHODS
122              
123             =head2 new()
124              
125             use Mewsoft::Pagination;
126             my $paginate = Mewsoft::Pagination->new(
127             total_entries => $total_entries,
128             entries_per_page => $entries_per_page,
129             current_page => $current_page,
130             pages_per_set => $pages_per_set,
131             mode => "slide", #modes are 'slide', 'fixed', default is 'slide'
132             );
133              
134             This is the constructor of the object.
135              
136             SETTINGS are passed in a hash like fashion, using key and value pairs. Possible settings are:
137              
138             B - how many data units you have,
139              
140             B - the number of entries per page to display,
141              
142             B - the current page number (defaults to page 1) and,
143              
144             B - how many pages to display, defaults to 10,
145              
146             B - the mode (which defaults to 'slide') determins how the paging will work.
147              
148             =back 4
149              
150             =cut
151              
152             #==========================================================
153             #==========================================================
154             sub new {
155 0     0 1   my ($class, %args) = @_;
156            
157 0           my $self = bless {}, $class;
158            
159             #while (my($key, $value)=each(%args)) {print ("$key = $value\n");}
160              
161 0           $args{total_entries} += 0;
162 0           $args{entries_per_page} += 0;
163 0           $args{current_page} += 0;
164 0           $args{pages_per_set} += 0;
165            
166 0           $args{entries_per_page} = int($args{entries_per_page});
167 0           $args{current_page} = int($args{current_page});
168 0           $args{pages_per_set} = int($args{pages_per_set});
169              
170 0           $self->{total_entries} = int($args{total_entries});
171 0 0         $self->{entries_per_page} = $args{entries_per_page} > 0 ? $args{entries_per_page} : 10;
172 0 0         $self->{current_page} = $args{current_page} > 0 ? $args{current_page} : 1;
173 0 0         $self->{pages_per_set} = $args{pages_per_set} > 0 ? $args{pages_per_set} : 5;
174              
175 0 0 0       if ( defined $args{mode} && $args{mode} eq 'fixed' ) {
176 0           $self->{mode} = 'fixed';
177             } else {
178 0           $self->{mode} = 'slide';
179             }
180            
181 0           $self->_do_calculation();
182              
183 0           return $self;
184             }
185             #==========================================================
186             sub _do_calculation {
187 0     0     my ($self) = shift;
188            
189             # Calculate the total pages & the last page number
190 0           $self->{last_page} = int ($self->{total_entries} / $self->{entries_per_page});
191 0 0         if (($self->{total_entries} % $self->{entries_per_page})) { $self->{last_page}++; }
  0            
192 0 0         $self->{last_page} = 1 if ($self->{last_page} < 1);
193 0           $self->{total_pages} = $self->{last_page};
194              
195 0 0         if ($self->{current_page} > $self->{last_page}) {$self->{current_page} = $self->{last_page};}
  0            
196              
197 0           $self->{first_page} = 1; #always = 1
198              
199             # calculate the first data entry on the current page
200 0 0         if ($self->{total_entries} == 0) {
201 0           $self->{first} = 0;
202             } else {
203 0           $self->{first} = (($self->{current_page} - 1) * $self->{entries_per_page}) + 1;
204             }
205            
206             # calculate the last data entry on the current page
207 0 0         if ($self->{current_page} == $self->{last_page}) {
208 0           $self->{last} = $self->{total_entries};
209             } else {
210 0           $self->{last} = ($self->{current_page} * $self->{entries_per_page});
211             }
212              
213             # Calculate entries on the current page
214 0 0         if ($self->{total_entries} == 0) {
215 0           $self->{entries_on_current_page} = 0;
216             } else {
217 0           $self->{entries_on_current_page} = $self->last - $self->first + 1;
218             }
219            
220             #calculate the previous page number if any
221 0 0         if ($self->{current_page} > 1) {
222 0           $self->{previous_page} = $self->{current_page} - 1;
223             } else {
224 0           $self->{previous_page} = undef;
225             }
226            
227             #calculate the next page number if any
228 0 0         $self->{next_page} = $self->{current_page} < $self->{last_page} ? $self->{current_page} + 1 : undef;
229            
230             #calculate pages sets
231 0           $self->_calculate_visible_pages();
232            
233             #check if the first page is currently in the pages set displayed
234 0 0         $self->{first_page_in_set} = @{$self->{Page_Set_Pages}}[0] == 1 ? 1 : 0;
  0            
235             #check if the last page is currently in the pages set displayed
236 0 0         $self->{last_page_in_set} = @{$self->{Page_Set_Pages}}[$#{$self->{Page_Set_Pages}}] == $self->{last_page} ? 1 : 0;
  0            
  0            
237             }
238             #==========================================================
239              
240             =head2 total_entries()
241              
242             $paginate->total_entries($total_entries);
243              
244             This method sets or returns the total_entries. If called without
245             any arguments it returns the current total entries.
246              
247             =cut
248              
249             sub total_entries {
250 0     0 1   my ($self) = shift;
251 0 0         if (@_) {
252 0           $self->{total_entries} = shift ;
253 0           $self->_do_calculation();
254             }
255 0           return $self->{total_entries};
256             }
257             #==========================================================
258              
259             =head2 entries_per_page()
260              
261             $paginate->entries_per_page($entries_per_page);
262              
263             This method sets or returns the entries per page (page size). If called without
264             any arguments it returns the current data entries per page.
265              
266             =cut
267              
268             sub entries_per_page {
269 0     0 1   my ($self) = shift;
270 0 0         if (@_) {
271 0           $self->{entries_per_page} = shift ;
272 0           $self->_do_calculation();
273             }
274 0           return $self->{entries_per_page};
275             }
276             #==========================================================
277              
278             =head2 current_page()
279              
280             $paginate->current_page($page_num);
281              
282             This method sets or returns the current page. If called without
283             any arguments it returns the current page number.
284              
285             =cut
286              
287             sub current_page {
288 0     0 1   my ($self) = shift;
289 0 0         if (@_) {
290 0           $self->{current_page} = shift ;
291 0           $self->_do_calculation();
292             }
293 0           return $self->{current_page};
294             }
295             #==========================================================
296              
297             =head2 mode()
298            
299             $paginate->mode('slide');
300              
301             This method sets or returns the pages set mode which takes only
302             two values 'fixed' or 'slide'. The default is 'slide'. The fixed mode will be
303             good if you want to display all the navigation pages.
304              
305             =cut
306              
307             sub mode {
308 0     0 1   my ($self) = shift;
309 0 0         if (@_) {
310 0           $self->{mode} = shift ;
311 0           $self->_do_calculation();
312             }
313 0           return $self->{mode};
314             }
315             #==========================================================
316              
317             =head2 pages_per_set()
318              
319             $paginate->pages_per_set($number_of_pages_per_set);
320              
321             Sets or returns the number of pages per set (visible pages).
322             If called without any arguments it will return the current
323             number of pages per set.
324              
325             =cut
326              
327             sub pages_per_set {
328 0     0 1   my ($self) = shift;
329 0 0         if (@_) {
330 0           $self->{pages_per_set} = shift ;
331 0           $self->_do_calculation();
332             }
333 0           return $self->{pages_per_set};
334             }
335             #==========================================================
336              
337             =head2 entries_on_current_page()
338              
339             $paginate->entries_on_current_page();
340              
341             This method returns the number of entries on the current page.
342              
343             =cut
344              
345             sub entries_on_current_page {
346 0     0 1   my ($self) = shift;
347              
348 0 0         if ($self->{total_entries} == 0) {
349 0           return 0;
350             } else {
351 0           return $self->last - $self->first + 1;
352             }
353             }
354             #==========================================================
355              
356             =head2 first_page()
357              
358             $paginate->first_page();
359              
360             Returns first page. Always returns 1.
361              
362             =cut
363              
364             sub first_page {
365 0     0 1   my ($self) = shift;
366 0           return 1;
367             }
368             #==========================================================
369              
370             =head2 last_page()
371              
372             $paginate->last_page();
373              
374             Returns the last page number, the total number of pages.
375              
376             =cut
377              
378             sub last_page {
379 0     0 1   my ($self) = shift;
380 0           return $self->{last_page};
381             }
382             #==========================================================
383              
384             =head2 total_pages()
385              
386             $paginate->total_pages();
387              
388             Returns the last page number, the total number of pages.
389              
390             =cut
391              
392             sub total_pages {
393 0     0 1   my ($self) = shift;
394 0           return $self->{last_page};
395             }
396             #==========================================================
397              
398             =head2 first()
399              
400             $paginate->first();
401              
402             Returns the number of the first entry on the current page.
403              
404             =cut
405              
406             sub first {
407 0     0 1   my ($self) = shift;
408 0           return $self->{first};
409             }
410             #==========================================================
411              
412             =head2 last()
413              
414             $paginate->last();
415              
416             Returns the number of the last entry on the current page.
417              
418             =cut
419              
420             sub last {
421 0     0 1   my ($self) = shift;
422 0           return $self->{last};
423             }
424             #==========================================================
425              
426             =head2 previous_page()
427              
428             $paginate->previous_page();
429              
430             Returns the previous page number, if one exists. Otherwise it returns undefined.
431              
432             =cut
433              
434             sub previous_page {
435 0     0 1   my ($self) = shift;
436 0           return $self->{previous_page};
437             }
438             #==========================================================
439              
440             =head2 next_page()
441              
442             $paginate->next_page();
443              
444             Returns the next page number, if one exists. Otherwise it returns undefined.
445              
446             =cut
447              
448             sub next_page {
449 0     0 1   my ($self) = shift;
450 0           return $self->{next_page};
451             }
452             #==========================================================
453              
454             =head2 first_page_in_set()
455              
456             $paginate->first_page_in_set();
457              
458             Returns 1 if the first page is in the current pages set. Otherwise it returns 0.
459              
460             =cut
461              
462             sub first_page_in_set {
463 0     0 1   my ($self) = shift;
464 0           return $self->{first_page_in_set};
465             }
466             #==========================================================
467              
468             =head2 last_page_in_set()
469              
470             $paginate->last_page_in_set();
471              
472             Returns 1 if the last page is in the current pages set. Otherwise it returns 0.
473              
474             =cut
475              
476             sub last_page_in_set {
477 0     0 1   my ($self) = shift;
478 0           return $self->{last_page_in_set};
479             }
480             #==========================================================
481             #==========================================================
482             #==========================================================
483             # The code below originally from the module Data::Pageset
484             sub _calculate_visible_pages {
485 0     0     my ($self)= shift;
486              
487 0 0         unless ( $self->{pages_per_set} > 1 ) {
488             # Only have one page in the set, must be page 1
489 0 0         $self->{Page_Set_Previous} = $self->{current_page} - 1 if ($self->{current_page} != 1);
490 0           $self->{Page_Set_Pages} = [1];
491 0 0         $self->{Page_Set_Next} = $self->{current_page} + 1 if ($self->{current_page} < $self->{last_page});
492             } else {
493 0 0         if ( $self->{mode} eq 'fixed' ) {
494 0           my $starting_page = $self->_calc_start_page($self->{pages_per_set});
495 0           my $end_page = $starting_page + $self->{pages_per_set} - 1;
496              
497 0 0         if ( $end_page < $self->{last_page}) {
498 0           $self->{Page_Set_Next} = $end_page + 1;
499             }
500              
501 0 0         if ( $starting_page > 1 ) {
502 0           $self->{Page_Set_Previous} = $starting_page - $self->{pages_per_set};
503 0 0         $self->{Page_Set_Previous} = 1 if $self->{Page_Set_Previous} < 1;
504             }
505              
506 0 0         $end_page = $self->{last_page} if ($self->{last_page} < $end_page);
507 0           $self->{Page_Set_Pages} = [ $starting_page .. $end_page ];
508             } else {
509              
510             # We're in slide mode
511              
512             # See if we have enough pages to slide
513 0 0         if ( $self->{pages_per_set} >= $self->{last_page} ) {
514              
515             # No sliding, no next/prev pageset
516 0           $self->{Page_Set_Pages} = [ '1' .. $self->{last_page} ];
517             } else {
518              
519             # Find the middle rounding down - we want more pages after, than before
520 0           my $middle = int( $self->{pages_per_set} / 2 );
521              
522             # offset for extra value right of center on even numbered sets
523 0           my $offset = 1;
524 0 0         if ( $self->{pages_per_set} % 2 != 0 ) {
525             # must have been an odd number, add one
526 0           $middle++;
527 0           $offset = 0;
528             }
529              
530 0           my $starting_page = $self->{current_page} - $middle + 1;
531 0 0         $starting_page = 1 if $starting_page < 1;
532 0           my $end_page = $starting_page + $self->{pages_per_set} - 1;
533 0 0         $end_page = $self->{last_page} if ($self->last_page() < $end_page);
534              
535 0 0         if ( $self->{current_page} <= $middle ) {
    0          
536             # near the start of the page numbers
537 0           $self->{Page_Set_Next} = $self->{pages_per_set} + $middle - $offset;
538 0           $self->{Page_Set_Pages} = [ '1' .. $self->{pages_per_set} ];
539             } elsif ( $self->{current_page} > ( $self->{last_page} - $middle - $offset ) )
540             {
541             # near the end of the page numbers
542 0           $self->{Page_Set_Previous} = $self->{last_page} - $self->{pages_per_set} - $middle + 1;
543 0           $self->{Page_Set_Pages}= [ ( $self->{last_page} - $self->{pages_per_set} + 1 ) .. $self->{last_page} ];
544             } else {
545             # Start scrolling
546 0           $self->{Page_Set_Pages} = [ $starting_page .. $end_page ];
547 0           $self->{Page_Set_Previous} = $starting_page - $middle - $offset;
548 0 0         $self->{Page_Set_Previous} = 1 if $self->{Page_Set_Previous} < 1;
549 0           $self->{Page_Set_Next} = $end_page + $middle;
550             }
551             }
552             }
553             }
554              
555             }
556             #==========================================================
557             # The code below originally from the module Data::Pageset
558             # Calculate the first page in the current set
559             sub _calc_start_page {
560 0     0     my ( $self) = @_;
561              
562 0           my $current_page_set = 0;
563              
564 0 0         if ( $self->{pages_per_set} > 0 ) {
565 0           $current_page_set = int( $self->{current_page} / $self->{pages_per_set} );
566 0 0         if ( $self->{current_page} % $self->{pages_per_set} == 0 ) {
567 0           $current_page_set = $current_page_set - 1;
568             }
569             }
570              
571 0           return ( $current_page_set * $self->{pages_per_set} ) + 1;
572             }
573             #==========================================================
574              
575             =head2 previous_set()
576              
577             print "Previous set starts at ", $paginate->previous_set(), "\n";
578              
579             This method returns the page number at the start of the previous page set.
580             undef is return if pages_per_set has not been set.
581              
582             =cut
583              
584             sub previous_set {
585 0     0 1   my $self = shift;
586 0 0         return $self->{Page_Set_Previous} if defined $self->{Page_Set_Previous};
587 0           return undef;
588             }
589             #==========================================================
590              
591             =head2 next_set()
592              
593             print "Next set starts at ", $paginate->next_set(), "\n";
594              
595             This method returns the page number at the start of the next page set.
596             undef is return if pages_per_set has not been set.
597              
598             =cut
599              
600             sub next_set {
601 0     0 1   my ($self) = shift;
602 0 0         return $self->{Page_Set_Next} if defined $self->{Page_Set_Next};
603 0           return undef;
604             }
605             #==========================================================
606              
607             =head2 pages_in_set()
608              
609             foreach my $page_num (@{$paginate->pages_in_set()}) {
610             print "Page: $page_num \n";
611             }
612              
613             This method returns an array ref of the the page numbers within
614             the current set. undef is return if pages_per_set has not been set.
615              
616             =cut
617              
618             sub pages_in_set {
619 0     0 1   my ($self) = shift;
620 0           return $self->{Page_Set_Pages};
621             }
622             #==========================================================
623             #==========================================================
624              
625             =head1 EXPORT
626              
627             None by default.
628              
629             =head1 AUTHOR
630              
631             Ahmed Amin Elsheshtawy,
632             Website: L
633              
634             =head1 SEE ALSO
635              
636             L.
637             L.
638              
639             =head1 COPYRIGHT AND LICENSE
640              
641             Copyright (C) 2008 by Ahmed Amin Elsheshtawy ,
642             L
643              
644             This module is free software; you can redistribute it and/or modify
645             it under the same terms as Perl itself.
646              
647             =cut
648              
649             1;