Back to documentation
package Statocles::Page::List;
our $VERSION = '0.094';
# ABSTRACT: A page presenting a list of other pages
use Statocles::Base 'Class';
with 'Statocles::Page';
use List::Util qw( reduce );
use Statocles::Template;
use Statocles::Page::ListItem;
use Statocles::Util qw( uniq_by );
=attr pages
The pages that should be shown in this list.
=cut
has _pages => (
is => 'ro',
isa => ArrayRef[ConsumerOf['Statocles::Page']],
init_arg => 'pages',
);
sub pages {
my ( $self ) = @_;
my %rewrite;
if ( $self->type eq 'application/rss+xml' || $self->type eq 'application/atom+xml' ) {
%rewrite = ( rewrite_mode => 'full' );
}
my @pages;
for my $page ( @{ $self->_pages } ) {
# Always re-wrap the page, even if it's already wrapped,
# to change the rewrite_mode
push @pages, Statocles::Page::ListItem->new(
%rewrite,
page => $page->isa( 'Statocles::Page::ListItem' ) ? $page->page : $page,
);
}
return \@pages;
}
=attr next
The path to the next page in the pagination series.
=attr prev
The path to the previous page in the pagination series.
=cut
has [qw( next prev )] => (
is => 'rw',
isa => PagePath,
coerce => PagePath->coercion,
);
=attr date
Get the date of this list. By default, this is the latest date of the first
page in the list of pages.
=cut
has '+date' => (
lazy => 1,
default => sub {
my ( $self ) = @_;
my $date = reduce { $a->epoch gt $b->epoch ? $a : $b }
map { $_->date }
@{ $self->pages };
return $date;
},
);
=attr search_change_frequency
Override the default L<search_change_frequency|Statocles::Page/search_change_frequency>
to C<daily>, because these pages aggregate other pages.
=cut
has '+search_change_frequency' => (
default => sub { 'daily' },
);
=attr search_priority
Override the default L<search_priority|Statocles::Page/search_priority> to reduce
the rank of list pages to C<0.3>.
It is more important for users to get to the full page than
to get to this list page, which may contain truncated content, and whose relevant
content may appear 3-4 items down the page.
=cut
has '+search_priority' => (
default => sub { 0.3 },
);
=method paginate
my @pages = Statocles::Page::List->paginate( %args );
Build a paginated list of L<Statocles::Page::List> objects.
Takes a list of key-value pairs with the following keys:
path - An sprintf format string to build the path, like '/page-%i.html'.
Pages are indexed started at 1.
index - The special, unique path for the first page. Optional.
pages - The arrayref of Statocles::Page::Document objects to paginate.
after - The number of items per page. Defaults to 5.
Return a list of Statocles::Page::List objects in numerical order, the index
page first (if any).
=cut
sub paginate {
my ( $class, %args ) = @_;
# Unpack the args so we can pass the rest to new()
my $after = delete $args{after} // 5;
my $pages = delete $args{pages};
my $path_format = delete $args{path};
my $index = delete $args{index};
# The date is the max of all input pages, since input pages get moved between
# all the list pages
my $date = reduce { $a->epoch gt $b->epoch ? $a : $b }
map { $_->date }
@$pages;
my @sets;
for my $i ( 0..$#{$pages} ) {
push @{ $sets[ int( $i / $after ) ] }, $pages->[ $i ];
}
my @retval;
for my $i ( 0..$#sets ) {
my $path = $index && $i == 0 ? $index : sprintf( $path_format, $i + 1 );
my $prev = $index && $i == 1 ? $index : sprintf( $path_format, $i );
my $next = $i != $#sets ? sprintf( $path_format, $i + 2 ) : '';
# Remove index.html from link URLs
s{/index[.]html$}{/} for ( $prev, $next );
push @retval, $class->new(
path => $path,
pages => $sets[$i],
( $next ? ( next => $next ) : () ),
( $i > 0 ? ( prev => $prev ) : () ),
date => $date,
%args,
);
}
return @retval;
}
=method vars
my %vars = $page->vars;
Get the template variables for this page.
=cut
around vars => sub {
my ( $orig, $self ) = @_;
return (
$self->$orig,
pages => $self->pages,
);
};
=method links
my @links = $page->links( $key );
Get the given set of links for this page. See L<the links
attribute|Statocles::Page/links> for some commonly-used keys.
For List pages, C<stylesheet> and C<script> links are also collected
from the L<inner pages|/pages>, to ensure that content in those pages
works correctly.
=cut
around links => sub {
my ( $orig, $self, @args ) = @_;
if ( @args > 1 || $args[0] !~ /^(?:stylesheet|script)$/ ) {
return $self->$orig( @args );
}
my @links;
for my $page ( @{ $self->pages } ) {
push @links, $page->links( @args );
}
push @links, $self->$orig( @args );
return uniq_by { $_->href } @links;
};
1;
__END__
=head1 DESCRIPTION
A List page contains a set of other pages. These are frequently used for index
pages.