make FeedGenerator pretty-print the XML
[scpubgit/SCS.git] / lib / SCSite / FeedGenerator.pm
1 package SCSite::FeedGenerator;
2
3 use Moo;
4 no warnings 'once';
5
6 has id_prefix => (is => 'ro', required => 1);
7 has pages => (is => 'ro', required => 1);
8
9 sub feed_http_response {
10   my ($self, $code, $feed_config) = @_;
11   $self->_feed_response(
12     $code, $self->_config_to_data($feed_config)
13   );
14 }
15
16 sub _config_to_data {
17   my ($self, $config) = @_;
18   my $base_page = $self->pages->get({ path => $config->{base} });
19   my @entry_pages = $base_page->children(%{$config->{entries}})
20                               ->latest(10)->flatten;
21   +{
22      %$config,
23      id => $self->_id_for($base_page->path),
24      web_url => $base_page->path,
25      feed_url => "/feed/${\$config->{base}}",
26      entries => [ map +{
27        title => $_->title,
28        summary_html => do {
29          use HTML::Tags;
30          HTML::Tags::to_html_string(<p>, $_->description, </p>)
31        },
32        content_html => $_->body,
33        created => $_->created,
34        web_url => $_->path,
35      }, @entry_pages ],
36   }
37 }
38
39 sub _id_for {
40   my ($self, $for) = @_;
41   join '', $self->id_prefix, $for;
42 }
43
44 sub _feed_response {
45   my ($self, $code, $data) = @_;
46   [ $code,
47     [ 'Content-type' => 'application/atom+xml' ],
48     [ $self->_feed_string($data) ]
49   ]
50 }
51
52 sub _feed_string {
53   my ($self, $data) = @_;
54   XML::Tags::to_xml_string(
55     $self->_feed_data_to_tags($data)
56   );
57 }
58
59 sub _feed_data_to_tags {
60   my ($self, $data) = @_;
61   use XML::Tags qw(
62     feed title subtitle link id
63   );
64   my ($web_url, $feed_url) = @{$data}{qw(web_url feed_url)};
65   (\'<?xml version="1.0" encoding="UTF-8"?>', "\n",
66   <feed xmlns="http://www.w3.org/2005/Atom">, "\n",
67     '  ', <title type="text">, $data->{title}, </title>, "\n",
68     ($data->{subtitle}
69       ? ('  ', <subtitle type="text">, $data->{subtitle}, </subtitle>, "\n",)
70       : ()),
71     '  ', <link rel="alternate" type="text/html" href="${web_url}" />, "\n",
72     '  ', <link rel="self" type="application/atom+xml" href="${feed_url}" />, "\n",
73     '  ', <id>, $data->{id}, </id>, "\n",
74     (map $self->_entry_data_to_tags($_), @{$data->{entries}}),
75   </feed>);
76 }
77
78 sub _entry_data_to_tags {
79   my ($self, $data) = @_;
80   use XML::Tags qw(entry title link id published updated summary content);
81   my $web_url = $data->{web_url};
82   '  ', <entry>, "\n",
83     '    ', <title>, $data->{title}, </title>, "\n",
84     '    ', <link href="${web_url}" />, "\n",
85     '    ', <id>, $self->_id_for($data->{web_url}), </id>, "\n",
86     '    ', <published>, $data->{created}, </published>, "\n",
87     '    ', <updated>, ($data->{created}||$data->{updated}), </updated>, "\n",
88     ($data->{summary_html}
89       ? ('    ', <summary type="html">, \($data->{summary_html}), </summary>, "\n")
90       : ()
91     ),
92     '    ', <content type="html">, \($data->{body_html}), </content>, "\n",
93   '  ', </entry>, "\n";
94 }
95
96 1;