# Copyright 2013-2014 Stefan Goebel.
#
# This file is part of Newcomen.
#
# Newcomen is free software: you can redistribute it and/or modify it under the terms of the GNU
# General Public License as published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# Newcomen is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along with Newcomen. If not, see
# .
package Newcomen::Plugin::Blog::Feed::Main;
our $VERSION = 2014052501;
use namespace::autoclean;
use Moose '-meta_name' => '_moose_meta';
use MooseX::StrictConstructor;
use Newcomen::Content;
use Newcomen::Util::Hash qw( merge );
use Newcomen::Util::Time;
use Newcomen::Util::UUID;
extends 'Newcomen::Plugin::Base';
with 'Newcomen::Role::Attribute::Catalog';
with 'Newcomen::Role::Attribute::Config';
with 'Newcomen::Role::Attribute::URL';
override '_build_default_config' => sub {{
'blog' => {
'feed' => {
'main' => {
'url' => undef,
'ascending' => undef,
'entries' => undef,
'feed_info' => {},
'formatters' => undef,
'renderer' => undef,
'writer' => undef,
},
},
},
}};
sub hook_build_collections {
my $self = shift;
my $main = $self -> _catalog () -> collection ('Blog::Index::Main');
return () unless $main;
my $collection = Newcomen::Collection -> new (
'creator' => 'Blog::Feed::Main', 'id' => 'Blog::Feed::Main'
);
$collection -> push ($_) for $main -> sources ();
my $asc = $self -> _config () -> get (['blog', 'feed', 'main', 'ascending'])
// $self -> _config () -> get (['blog', 'feed', 'defaults', 'ascending']);
$collection -> sort (
sub {
my $a = $_ [0] -> get (['time', 'published', 'epoch']) // confess 'No epoch set';
my $b = $_ [1] -> get (['time', 'published', 'epoch']) // confess 'No epoch set';
return $asc ? ($a <=> $b) : ($b <=> $a);
}
);
$collection -> set (['order_ascending'], $asc);
return ($collection);
}
sub hook_build_pages {
my $self = shift;
my $coll = $self -> _catalog () -> collection ('Blog::Feed::Main');
my $url = $self -> _config () -> get (['blog', 'feed', 'main', 'url']);
return () unless $coll and $url;
my $entries = $self -> _config () -> get (['blog', 'feed', 'main', 'entries'])
// $self -> _config () -> get (['blog', 'feed', 'defaults', 'entries'])
// 5;
confess 'Invalid entries value' unless $entries =~ /^\d+$/;
$entries = $coll -> count () if $entries == 0;
my $iterator = $coll -> paginate ($entries);
my $page = Newcomen::Page -> new (
'target' => $url,
'creator' => 'Blog::Feed::Main',
'content' => [ map { Newcomen::Content -> new ('source' => $_) } $iterator -> () ],
'collection' => $coll,
);
$self -> _url () -> set (['Blog::Feed::Main'], $page -> target ());
if (my $index_coll = $self -> _catalog () -> collection ('Blog::Index::Main')) {
$index_coll -> set (['atom_url'], $page -> target ());
}
my $info_1 = $self -> _config () -> get (['blog', 'feed', 'main', 'feed_info']) // {};
my $info_2 = $self -> _config () -> get (['blog', 'feed', 'defaults', 'feed_info']) // {};
my $info_3 = $self -> _config () -> get (['blog', 'defaults', 'page_info']) // {};
my $merged = merge ($info_3, merge ($info_2, $info_1));
$page -> set (["atom_$_"], $merged -> {$_}) for keys %$merged;
unless ($page -> get (['atom_uuid'])) {
my $ns = $self -> _config () -> get (['blog', 'feed', 'defaults', 'uuid_ns']);
confess 'UUID namespace required' unless $ns;
$page -> set (['atom_uuid'], Newcomen::Util::UUID::uuid_v5 ($ns, "Blog::Feed::Main"));
}
if (not $page -> get (['atom_updated'])) {
my $updt;
if ($page -> count ()) {
my $last = $page -> content ($coll -> get (['order_ascending']) ? -1 : 0);
$updt = $last -> get (['time', 'modified', 'iso' ]);
$updt .= $last -> get (['time', 'modified', 'offset']);
}
else {
my $time = Newcomen::Util::Time::parse_time (time, '%s');
$updt = $time -> {'iso'} . $time -> {'offset'};
}
$page -> set (['atom_updated'], $updt);
}
return ($page);
}
sub hook_formatters {
my $self = shift;
my $content = shift;
my $page = shift;
my $index = shift;
return unless $page -> creator () eq 'Blog::Feed::Main';
$content -> formatters () -> add (
$self -> _config () -> get (['blog', 'feed', 'main', 'formatters']) // []
);
}
sub hook_renderer {
my $self = shift;
my $page = shift;
$page -> set_renderer ($self -> _config () -> get (['blog', 'feed', 'main', 'renderer']));
}
sub hook_writer {
my $self = shift;
my $page = shift;
$page -> set_writer ($self -> _config () -> get (['blog', 'feed', 'main', 'writer']));
}
__PACKAGE__ -> _moose_meta () -> make_immutable ();
1;
__END__
####################################################################################################
=head1 NAME
Newcomen::Plugin::Blog::Feed::Main - Creates the feed for the main index page.
=head1 DESCRIPTION
This plugin may be used to generate the atom feed for the main index page created by the plugin
L.
Please read the documentation of L first!
=head2 Collections
A new collection will be created for the feed, based on the original index collection. The
collection's ID and the creator will both be set to C<'Blog::Feed::Main'>. The index collection's
meta data will be copied to the new collection, and all the sources from the index collection will
be added to the feed collection. Sorting of the feed collection is independent from the index
collection, see L.
The meta data I will be set for the original index collection. Its value will be the page
target (the URL of the feed).
=head2 Pages
One page will be created for the feed. The page's creator will be set to C<'Blog::Feed::Main'>. The
target and the number of articles will be set to the configured values, see L. The
page's collection attribute will be set to the source collection of the feed page. See
L for details on the meta data of the page.
An entry in the global URL map (see L) will be created for the feed page. The key
will be set to C<'Blog::Feed::Main'>.
=head1 OPTIONS
{
'blog' => {
'feed' => {
'main' => {
'url' => undef,
'ascending' => undef,
'entries' => undef,
'feed_info' => {},
'formatters' => undef,
'renderer' => undef,
'writer' => undef,
},
},
},
}
These are the default options set by this plugin. They may be overridden by user configuration.
I specifies the page target.
I sets the order of the articles in the feed. If set to a true value, articles will be
in ascending order, i.e. oldest first. If this is C (the default), the value of the option
I will be checked. If this, too, is not set, it defaults to false.
Note that the order is determined by the modification time, not the publication time as is used for
the index pages!
I specifies the number of articles in the feed. If this is C (the default), the
value of the option I will be checked. If this, too, is not set, it
defaults to C<5>. If I is set to C<0>, all articles will be included in the feed.
The I hashref may be used to set arbitrary data that will be included in the page's meta
data. Everything set in this hashref will be included in the meta data, with the original keys being
prefixed with C<'atom_'>. Before being copied to the meta data, this hashref will be merged with
the hashrefs specified by the I and I
options, with more specific data overriding less specific data if necessary.
Note that if there is no I key in the I hashref (after merging), a UUID will be
created for the feed. For this to work, the setting I has to be set,
please see L for details. If this options is not set, and
there is no UUID in the info hashref, this plugin will I.
Also, if there is no I key in the I hashref, the I meta data will
be set automatically based on the modification time information of the sources.
I, I and I may be used to specify formatter backends for the feed
content, and renderer/writer backends for the feed page. The format is the same as described for the
options in L, please see there for details. If these are C
(the default), no backends will be set, and another plugin may set these.
=head1 META DATA
=head2 Collections
{
'order_ascending' => ,
'atom_url' => ,
}
The I configuration option (determined as described above) will be included in the
collection meta data of the feed collection.
The I will be set to the feed URL (page target) for the B (created by
the L plugin), not the feed collection!
=head2 Pages
{
'atom_uuid' => ,
'atom_updated' => ,
}
All meta data specified in the I hashref (see L) will be set for the
pages, keys will be prefixed by C<'atom_'>. Additionally, even if the I hashref does not
contain the I and I keys, I and I will be set for every page
(if these are included in the I hashref, the configured values will be used).
=head1 HOOKS
This plugin implements the following hooks (with default priority unless stated otherwise):
I (priority C<600>), I, I,
I, I.
=head1 SEE ALSO
L, L,
L, L
=head1 VERSION
This is version C<2014052501>.
=head1 AUTHOR
Stefan Goebel - newcomen {at} subtype {dot} de
=head1 COPYRIGHT AND LICENSE
Copyright 2013-2014 Stefan Goebel.
This file is part of Newcomen.
Newcomen is free software: you can redistribute it and/or modify it under the terms of the
L as published by the
L, either version 3 of the license, or (at your
option) any later version.
Newcomen is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
L for more details.
You should have received a copy of the
L along with Newcomen. If not, see
>.
=cut
####################################################################################################
# :indentSize=3:tabSize=3:noTabs=true:mode=perl:maxLineLen=100: