package Miril::List;
use strict;
use warnings;
use autodie;
use Carp qw(croak);
use Ref::List qw(list);
use List::Util qw(first);
use Miril::DateTime;
### ACCESSORS ###
use Object::Tiny qw(
posts
key
count
title
url
sort
id
);
### CONSTRUCTOR ###
sub new {
my $class = shift;
my %params = @_;
my $posts = $params{posts};
my $self = bless \%params, $class;
$self->{count} = list $params{posts};
return $self;
}
### METHODS ###
sub group
{
my $self = shift;
my $group_key = shift;
return $self->{group_key} unless $group_key;
$self->{group_key} = $group_key;
my ($obj_cb, $key_cb);
# must be perl 5.8-compatible so we can't use switch
if ($group_key eq 'topic')
{
$obj_cb = sub {
my ($post, $id) = @_;
return first {$_->id eq $id} list $post->topics;
};
$key_cb = sub { map {$_->id} list shift->topics };
}
elsif ($group_key eq 'type')
{
$obj_cb = sub { shift->type };
$key_cb = sub { shift->type->id };
}
elsif ($group_key eq 'author')
{
$obj_cb = sub { shift->author };
$key_cb = sub { shift->author };
}
elsif ($group_key eq 'year')
{
if ($self->sort eq 'modified')
{
$obj_cb = sub { shift->modified };
$key_cb = sub { shift->modified->strftime('%Y') };
}
else
{
$obj_cb = sub { shift->published };
$key_cb = sub { shift->published->strftime('%Y') };
}
}
elsif ($group_key eq 'month')
{
if ($self->sort eq 'modified')
{
$obj_cb = sub { shift->modified };
$key_cb = sub { shift->modified->strftime('%Y%m') };
}
else
{
$obj_cb = sub { shift->published };
$key_cb = sub { shift->published->strftime('%Y%m') };
}
}
elsif ($group_key eq 'date')
{
if ($self->sort eq 'modified')
{
$obj_cb = sub { shift->modified };
$key_cb = sub { shift->modified->strftime('%Y%m%d') };
}
else
{
$obj_cb = sub { shift->published };
$key_cb = sub { shift->published->strftime('%Y%m%d') };
}
}
else
{
croak "Invalid key '" . $group_key . "' passed to group.";
}
my (%groups, @groups);
foreach my $post (list $self->posts)
{
my @group_hashes = $key_cb->($post);
foreach my $group_hash (@group_hashes)
{
my @group;
@group = @{ $groups{$group_hash} } if $groups{$group_hash};
push @group, $post;
$groups{$group_hash} = \@group;
}
}
push @groups, Miril::List->new(
posts => $groups{$_},
key => $obj_cb->($groups{$_}->[-1], $_),
title => $self->title,
sort => $self->sort,
id => $self->id,
) for sort keys %groups;
return @groups;
}
sub post_by_id
{
my $self = shift;
my $id = shift;
return first { $_ eq $id } list $self->posts;
}
sub timestamp
{
return Miril::DateTime->new(time());
}
1;