Plagger::Plugin::Filter::Sort

nirvashさんがつくったFilter::Reverseでも十分用事は足りるんですが、$feed->sort_entriesを使わなくてもconfigだけでいろいろソートできるとうれしいなと思ったので書いてみた。車輪の再発明かも。reverseオプションは単なるおまけ。

package Plagger::Plugin::Filter::Sort;
use strict;
use base qw( Plagger::Plugin );

our $VERSION = '0.01';

sub register {
    my ($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.feed.fixup'  => \&sort,
    );
}

sub sort {
    my ($self, $context, $args) = @_;

    my @entries = reverse $args->{feed}->entries;

    my @sort_by = 
        map { [ each %{ $_ } ] }
            ref $self->conf->{sort_by} eq 'ARRAY' ?
            @{ $self->conf->{sort_by} } : ( $self->conf->{sort_by} );

    if (@sort_by) {
        my @schwarz = ();
        foreach my $entry (@entries) {
            my @array = ();
            foreach my $sort (@sort_by) {
                my $key = $sort->[0];
                if ( $entry->can($key) ) {
                    push @array, $entry->$key();
                }
            }
            push @array, $entry;
            push @schwarz, \@array;
        }

        @entries = 
            map  { $_->[-1] }
            sort {
                for ( my $ct = 0, my $last = @sort_by; $ct < $last; $ct++ ) {
                    if ($sort_by[$ct]->[1] eq 'asc_num') {
                        my $ret = $a->[$ct] <=> $b->[$ct];
                        return $ret if $ret;
                    }
                    if ($sort_by[$ct]->[1] eq 'asc_str') {
                        my $ret = $a->[$ct] cmp $b->[$ct];
                        return $ret if $ret;
                    }
                    if ($sort_by[$ct]->[1] eq 'desc_num') {
                        my $ret = $b->[$ct] <=> $a->[$ct];
                        return $ret if $ret;
                    }
                    if ($sort_by[$ct]->[1] eq 'desc_str') {
                        my $ret = $b->[$ct] cmp $a->[$ct];
                        return $ret if $ret;
                    }
                }
            }
            @schwarz;
    }

    @entries = reverse @entries if $self->conf->{reverse};

    $args->{feed}->{entries} = \@entries;
}

1;

__END__

=head1 NAME

Plagger::Plugin::Filter::Sort - sort the order of the entries

=head1 SYNOPSIS

  - module: Filter::Sort
    config:
    sort_by:
      - id: asc_num
      - link: desc_str
    reverse: 1

=head1 CONFIG

=head2 sort_by (optional)

By which you want to sort entries.

=head2 reverse (optional)

Just for convenience. If set to true, the order will be reversed.

=head1 AUTHOR

Kenichi Ishigaki

=head1 SEE ALSO

L<Plagger>

=cut