Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

initial reimplementation

  • Loading branch information...
commit 2e9f1c38010b5fac622a2611d670aa01c9186ba8 1 parent 7637e46
Yann Kerhervé yannk authored
99 lib/Data/Page/FlickrLike.pm
@@ -16,6 +16,17 @@ our $OuterWindow = 2;
16 16 our $MinLength = 7;
17 17 our $GlueLength = 2;
18 18
  19 +
  20 +sub get_min_fill {
  21 + my ($page, $first_page, $last_page, $min) = @_;
  22 + my $length = $last_page - $first_page + 1 < $min
  23 + ? $last_page - $first_page + 1
  24 + : $min;
  25 +
  26 + my $current_length = scalar @$page;
  27 + return $length - $current_length;
  28 +}
  29 +
19 30 sub Data::Page::navigations {
20 31 my ($self, $args) = @_;
21 32 my $nav;
@@ -31,30 +42,84 @@ sub Data::Page::navigations {
31 42 my $min = exists $args->{min_length}
32 43 ? $args->{min_length}
33 44 : $Data::Page::FlickrLike::MinLength;
34   - my $glue = exists $args->{glue_length}
  45 + my $glue_length = exists $args->{glue_length}
35 46 ? $args->{glue_length}
36 47 : $Data::Page::FlickrLike::GlueLength;
37 48
38   - for my $page ($self->first_page .. $self->last_page) {
39   - if (( $page >= $self->current_page - ($inner)
40   - && $page <= $self->current_page + ($inner)) ||
41   - ($self->current_page <= $self->first_page + ($inner + $glue + $outer)
42   - && $page < $self->first_page + $min ) ||
43   - ($self->current_page >= $self->last_page - ($inner + $glue + $outer)
44   - && $page > $self->last_page - $min) ||
45   - ($page < $self->first_page + $outer) ||
46   - ($page > $self->last_page - $outer)) {
47   - push @$nav, $page;
  49 + my $current_page = $self->current_page;
  50 + my $last_page = $self->last_page;
  51 + my $first_page = $self->first_page;
  52 +
  53 + ## build the pages around current_page to begin with
  54 + for (my $i = $current_page - $inner; $i <= $current_page + $inner ; $i++) {
  55 + push @$nav, $i if $i >= $first_page && $i <= $last_page;
  56 + }
  57 +
  58 + ## shortcut if we already take all the room
  59 + if ($nav->[0] == $first_page && $nav->[-1] == $last_page) {
  60 + return wantarray ? @$nav : $nav;
  61 + }
  62 +
  63 + ## NOTE: there are some extra operations in there just in case $first_page != 1
  64 + ## but, this shouldn't really be necessary...
  65 +
  66 + if ($nav->[0] == $first_page && $nav->[-1] != $last_page) {
  67 + ## we're stuck at the beginning, check for $min_lengh
  68 + my $min_fill = get_min_fill($nav, $first_page, $last_page, $min);
  69 + my $last = $nav->[-1];
  70 + push @$nav, map { $last + $_ } (1 .. $min_fill);
  71 + }
  72 +
  73 + ## stuck at the end: fill the beginning using $min_length
  74 + elsif ($nav->[0] != $first_page && $nav->[-1] == $last_page) {
  75 + my $min_fill = get_min_fill($nav, $first_page, $last_page, $min);
  76 + my $first = $nav->[0];
  77 + unshift @$nav, reverse map { $first - $_ } (1 .. $min_fill);
  78 + }
  79 +
  80 + ## now, care about extremities specifically
  81 + my (@begin, @end);
  82 + for (0 .. ($outer - 1)) {
  83 + push @begin, $first_page + $_;
  84 + push @end, $last_page - $_;
  85 + }
  86 + @end = reverse @end;
  87 +
  88 + ## we might need some glue
  89 + if ($begin[-1] < $nav->[0] - 1) {
  90 + my $to_glue = $nav->[0] - $begin[-1] - 1;
  91 + if ($to_glue <= $glue_length) {
  92 + ## we can glue!
  93 + my $last = $begin[-1];
  94 + push @begin, map { $last + $_ } (1 .. $to_glue);
  95 +
48 96 }
49   - elsif ( ($page < $self->current_page && $prev_skip ) ) {
50   - push @$nav, 0;
51   - $prev_skip--;
  97 + else {
  98 + push @begin, 0;
52 99 }
53   - elsif ( ($page > $self->current_page && $next_skip ) ) {
54   - push @$nav, 0;
55   - $next_skip--;
  100 + }
  101 + if ($end[0] > $nav->[-1] + 1) {
  102 + my $to_glue = $end[0] - $nav->[-1] - 1;
  103 + if ($to_glue <= $glue_length) {
  104 + ## we can glue!
  105 + my $first = $end[0];
  106 + unshift @end, reverse map { $first - $_ } (1 .. $to_glue);
  107 + }
  108 + else {
  109 + unshift @end, 0;
56 110 }
57 111 }
  112 +
  113 + ## trim redundant items if they exist
  114 + while (@begin && $begin[-1] >= $nav->[0]) {
  115 + pop @begin;
  116 + };
  117 + while (@end && $end[0] && $end[0] <= $nav->[-1]) {
  118 + shift @end;
  119 + };
  120 +
  121 + $nav = [ @begin, @$nav, @end ];
  122 +
58 123 return wantarray ? @$nav : $nav;
59 124 }
60 125
2  t/01.navigations.t
... ... @@ -1,4 +1,4 @@
1   -use Test::More tests => 22;
  1 +use Test::More tests => 30;
2 2
3 3 use Data::Page;
4 4 use Data::Page::FlickrLike;
6 t/02.example.t
... ... @@ -1,4 +1,4 @@
1   -use Test::More tests => 22;
  1 +use Test::More tests => 30;
2 2
3 3 use Data::Page;
4 4 use Data::Page::FlickrLike;
@@ -10,8 +10,8 @@ for my $test (@$tests) {
10 10 my $pager = Data::Page->new();
11 11 $pager->$_($test->{input}{$_})
12 12 for qw(total_entries entries_per_page current_page);
13   - my $out = join (' | ',
  13 + my $out = join (' | ',
14 14 map { $_ == 0 ? '...' : $_} @{$pager->navigations});
15   - ok( $out eq $test->{expected}->{out},
  15 + ok( $out eq $test->{expected}->{out},
16 16 'current_page ' . $test->{input}{current_page});
17 17 }
66 t/test.yaml
... ... @@ -1,3 +1,5 @@
  1 +## test for 0 page
  2 +## test for weird boundaries
1 3 -
2 4 input:
3 5 total_entries: 100
@@ -174,3 +176,67 @@
174 176 expected:
175 177 navigations: [1, 2, 0, 61, 62, 63, 64, 65, 66, 67]
176 178 out: 1 | 2 | ... | 61 | 62 | 63 | 64 | 65 | 66 | 67
  179 +-
  180 + input:
  181 + total_entries: 1000000
  182 + entries_per_page: 18
  183 + current_page: 68
  184 + expected:
  185 + navigations: [1, 2, 0, 65, 66, 67, 68, 69, 70, 71, 0, 55555, 55556]
  186 + out: 1 | 2 | ... | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ... | 55555 | 55556
  187 +-
  188 + input:
  189 + total_entries: 100000000
  190 + entries_per_page: 10
  191 + current_page: 99999999
  192 + expected:
  193 + navigations: [1, 2, 0, 9999994, 9999995, 9999996, 9999997, 9999998, 9999999, 10000000]
  194 + out: 1 | 2 | ... | 9999994 | 9999995 | 9999996 | 9999997 | 9999998 | 9999999 | 10000000
  195 +-
  196 + input:
  197 + total_entries: 100000000
  198 + entries_per_page: 10
  199 + current_page: 100000
  200 + expected:
  201 + navigations: [1, 2, 0, 99997, 99998, 99999, 100000, 100001, 100002, 100003, 0, 9999999, 10000000]
  202 + out: 1 | 2 | ... | 99997 | 99998 | 99999 | 100000 | 100001 | 100002 | 100003 | ... | 9999999 | 10000000
  203 +-
  204 + input:
  205 + total_entries: 100000000
  206 + entries_per_page: 1
  207 + current_page: 100000
  208 + expected:
  209 + navigations: [1, 2, 0, 99997, 99998, 99999, 100000, 100001, 100002, 100003, 0, 99999999, 100000000]
  210 + out: 1 | 2 | ... | 99997 | 99998 | 99999 | 100000 | 100001 | 100002 | 100003 | ... | 99999999 | 100000000
  211 +-
  212 + input:
  213 + total_entries: 100000000
  214 + entries_per_page: 100000000
  215 + current_page: 1
  216 + expected:
  217 + navigations: [ 1 ]
  218 + out: 1
  219 +-
  220 + input:
  221 + total_entries: 100000000
  222 + entries_per_page: 1000000000
  223 + current_page: 1
  224 + expected:
  225 + navigations: [ 1 ]
  226 + out: 1
  227 +-
  228 + input:
  229 + total_entries: 0
  230 + entries_per_page: 10
  231 + current_page: 1
  232 + expected:
  233 + navigations: [ 1 ]
  234 + out: 1
  235 +-
  236 + input:
  237 + total_entries: 0
  238 + entries_per_page: 1
  239 + current_page: 0
  240 + expected:
  241 + navigations: [ 1 ]
  242 + out: 1

0 comments on commit 2e9f1c3

Please sign in to comment.
Something went wrong with that request. Please try again.