File Coverage

blib/lib/Dancer2/Plugin/PageHistory/PageSet.pm
Criterion Covered Total %
statement 50 51 98.0
branch 13 16 81.2
condition 11 15 73.3
subroutine 13 13 100.0
pod 5 5 100.0
total 92 100 92.0


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::PageHistory::PageSet;
2              
3             =head1 NAME
4              
5             Dancer2::Plugin::PageHistory::PageSet - collection of pages with accessors
6              
7             =cut
8              
9 5     5   181809 use Carp qw(croak);
  5         6  
  5         231  
10 5     5   18 use Scalar::Util qw(blessed);
  5         7  
  5         203  
11 5     5   448 use Sub::Quote qw(quote_sub);
  5         8016  
  5         179  
12 5     5   386 use Dancer2::Core::Types qw(ArrayRef HashRef InstanceOf Int Maybe Str);
  5         5863  
  5         360  
13 5     5   439 use Moo;
  5         1976  
  5         24  
14 5     5   3673 use namespace::clean;
  5         30391  
  5         17  
15              
16             =head1 ATTRIBUTES
17              
18             =head2 default_type
19              
20             For all methods that expect an argument C then this C
21             will be the one used when C is not specified. Defaults to C.
22              
23             =cut
24              
25             has default_type => (
26             is => 'ro',
27             isa => Str,
28             default => 'default',
29             );
30              
31             =head2 fallback_page
32              
33             In the event that L or L have no page to
34             return then L is returned instead.
35              
36             By default this is set to undef.
37              
38             You can set this page to something else by passing any of the following as
39             the value of this attribute:
40              
41             =over
42              
43             =item * a hash reference to be passed to Dancer2::Plugin::PageHistory::Page->new
44              
45             =item * a Dancer2::Plugin::PageHistory::Page object
46              
47             =back
48              
49             =cut
50              
51             has fallback_page => (
52             is => 'ro',
53             isa => Maybe [ InstanceOf ['Dancer2::Plugin::PageHistory::Page'] ],
54             default => undef,
55             coerce => sub {
56             $_[0] ? Dancer2::Plugin::PageHistory::Page->new( %{ $_[0] } ) : undef;
57             },
58             );
59              
60             =head2 max_items
61              
62             The maximum number of each history C stored in L.
63              
64             =cut
65              
66             has max_items => (
67             is => 'ro',
68             isa => Int,
69             default => 10,
70             );
71              
72             =head2 pages
73              
74             A hash reference of arrays of hash references.
75              
76             Primary key is the history C such as C or C. For each
77             C an array reference of pages is stored with new pages added at
78             the start of the array reference.
79              
80             =cut
81              
82             has pages => (
83             is => 'rw',
84             isa => HashRef [
85             ArrayRef [ InstanceOf ['Dancer2::Plugin::PageHistory::Page'] ] ],
86             coerce => \&_coerce_pages,
87             predicate => 1,
88             );
89              
90             sub _coerce_pages {
91 29     29   751 my %pages;
92 29         44 while ( my ( $type, $list ) = each %{ $_[0] } ) {
  61         334  
93 32         62 foreach my $page (@$list) {
94 57 50 33     398 if ( !blessed($page) && ref($page) eq 'HASH' ) {
95 57         51 push @{ $pages{$type} },
  57         948  
96             Dancer2::Plugin::PageHistory::Page->new(%$page);
97             }
98             }
99             }
100 29         362 return \%pages;
101             }
102              
103             =head2 methods
104              
105             An array reference of extra method names that should be added to the class.
106             For example if one of these method names is 'product' then the following
107             shortcut method will be added:
108              
109             sub product {
110             return shift->pages->{"product"};
111             }
112              
113             =cut
114              
115             has methods => (
116             is => 'ro',
117             isa => ArrayRef,
118             default => sub { [] },
119             trigger => 1,
120             );
121              
122             sub _trigger_methods {
123 19     19   2030 my ( $self, $methods ) = @_;
124 19         43 foreach my $method (@$methods) {
125 39 100       668 unless ( $self->can($method) ) {
126 9         35 quote_sub "Dancer2::Plugin::PageHistory::PageSet::$method",
127             q{ return shift->pages->{$type} || []; },
128             { '$type' => \$method };
129             }
130             }
131             }
132              
133             =head1 METHODS
134              
135             =head2 add( %args )
136              
137             C<$args{type}> defaults to L.
138              
139             In addition to C other arguments should be those passed to C in
140             L.
141              
142             =cut
143              
144             sub add {
145 22     22 1 3542 my ( $self, %args ) = @_;
146              
147 22   66     109 my $type = delete $args{type} || $self->default_type;
148              
149 22         339 my $page = Dancer2::Plugin::PageHistory::Page->new(%args);
150              
151 19 100 66     1225 if ( !$self->pages->{$type}
      100        
152             || !$self->pages->{$type}->[0]
153             || $self->pages->{$type}->[0]->uri ne $page->uri )
154             {
155              
156             # not same uri as newest items on this list so add it
157              
158 17         1377 unshift( @{ $self->pages->{$type} }, $page );
  17         213  
159              
160             # trim to max_items if necessary
161 4         67 pop @{ $self->pages->{$type} }
162 17 100       89 if @{ $self->pages->{$type} } > $self->max_items;
  17         208  
163             }
164             }
165              
166             =head2 has_pages
167              
168             Predicate on L.
169              
170             =head2 page_index($index, $type)
171              
172             Returns the page from L of type C<$type> at position C<$index>.
173             If C<$type> is not supplied then L will be used.
174             If page is not found then L is returned instead.
175              
176             =cut
177              
178             sub page_index {
179 37     37 1 329 my ( $self, $index, $type ) = @_;
180              
181 37 50       86 croak "index arg must be supplied to page_index" unless defined $index;
182 37 100       113 $type = $self->default_type unless $type;
183              
184 37 100 100     660 if ( $self->has_pages && defined $self->pages->{$type}->[$index] ) {
185 26         492 return $self->pages->{$type}->[$index];
186             }
187 11         81 return $self->fallback_page;
188             }
189              
190             =head2 latest_page($type)
191              
192             A convenience method equivalent to:
193              
194             page_index(0, $type)
195              
196             =cut
197              
198             sub latest_page {
199 20     20 1 16661 return shift->page_index( 0, shift );
200             }
201              
202             =head2 previous_page
203              
204             A convenience method equivalent to:
205              
206             page_index(1, $type)
207              
208             =cut
209              
210             sub previous_page {
211 16     16 1 3326 return shift->page_index( 1, shift );
212             }
213              
214             =head2 types
215              
216             Return all of the page types currently stored in history.
217              
218             In array context returns an array of type names (keys of L)
219             and in scalar context returns the same as an array reference.
220              
221             =cut
222              
223             sub types {
224 2     2 1 1319 my $self = shift;
225 2 50       4 wantarray ? keys %{ $self->pages } : [ keys %{ $self->pages } ];
  2         22  
  0            
226             }
227              
228             1;