domain support for feeds, factor out sc-specific bits
[scpubgit/SCS.git] / lib / SCSite / FeedGenerator.pm
CommitLineData
221c4151 1package SCSite::FeedGenerator;
2
da140bff 3use URI;
221c4151 4use Moo;
5no warnings 'once';
6
221c4151 7has pages => (is => 'ro', required => 1);
8
9sub feed_http_response {
da140bff 10 my ($self, $code, $feed_config, $env) = @_;
221c4151 11 $self->_feed_response(
da140bff 12 $code, $self->_config_to_data($feed_config, $env)
221c4151 13 );
14}
15
16sub _config_to_data {
da140bff 17 my ($self, $config, $env) = @_;
18 my $url_scheme = $env->{'psgi.url_scheme'} || "http";
19 my $url_port = $env->{SERVER_PORT}||80;
20 my $base_url = URI->new(
21 $url_scheme
22 .'://'
23 .($env->{HTTP_HOST}
24 or (
25 ($env->{SERVER_NAME} || "")
26 .($url_scheme eq 'http' && $url_port == 80
27 ? ''
28 : ":${url_port}"
29 )
30 ))
31 .($env->{SCRIPT_NAME} || '/')
32 );
33 my $abs = sub { URI->new_abs($_[0], $base_url)->as_string };
221c4151 34 my $base_page = $self->pages->get({ path => $config->{base} });
35 my @entry_pages = $base_page->children(%{$config->{entries}})
36 ->latest(10)->flatten;
b0df368c 37 my $updated = (sort map $_->created, @entry_pages)[-1];
221c4151 38 +{
39 %$config,
da140bff 40 id => $abs->("feed/${\$config->{base}}/"),
41 web_url => $abs->($config->{base}.'/'),
42 feed_url => $abs->("feed/${\$config->{base}}/"),
b0df368c 43 updated => join('T', split(' ',$updated)).'Z',
da140bff 44 entries => [ map {
45 my $page_url = $abs->(do { (my $p = $_->path) =~ s/^\///; "$p/" });
46 +{
47 title => $_->title,
48 summary_html => do {
49 use HTML::Tags;
50 join '', HTML::Tags::to_html_string(<p>, $_->description, </p>)
51 },
52 content_html => $self->_absolutify_html($_->body, $base_url, $page_url),
53 created => join('T', split(' ',$_->created)).'Z',
54 web_url => $page_url,
55 }
56 } @entry_pages ],
221c4151 57 }
58}
59
221c4151 60sub _feed_response {
61 my ($self, $code, $data) = @_;
62 [ $code,
63 [ 'Content-type' => 'application/atom+xml' ],
64 [ $self->_feed_string($data) ]
65 ]
66}
67
68sub _feed_string {
69 my ($self, $data) = @_;
70 XML::Tags::to_xml_string(
71 $self->_feed_data_to_tags($data)
72 );
73}
74
75sub _feed_data_to_tags {
76 my ($self, $data) = @_;
77 use XML::Tags qw(
78 feed title subtitle link id
79 );
80 my ($web_url, $feed_url) = @{$data}{qw(web_url feed_url)};
8509b33b 81 (\'<?xml version="1.0" encoding="UTF-8"?>', "\n",
82 <feed xmlns="http://www.w3.org/2005/Atom">, "\n",
83 ' ', <title type="text">, $data->{title}, </title>, "\n",
221c4151 84 ($data->{subtitle}
8509b33b 85 ? (' ', <subtitle type="text">, $data->{subtitle}, </subtitle>, "\n",)
221c4151 86 : ()),
8509b33b 87 ' ', <link rel="alternate" type="text/html" href="${web_url}" />, "\n",
88 ' ', <link rel="self" type="application/atom+xml" href="${feed_url}" />, "\n",
b0df368c 89 ' ', <updated>, $data->{updated}, </updated>, "\n",
8509b33b 90 ' ', <id>, $data->{id}, </id>, "\n",
221c4151 91 (map $self->_entry_data_to_tags($_), @{$data->{entries}}),
92 </feed>);
93}
94
95sub _entry_data_to_tags {
96 my ($self, $data) = @_;
b0df368c 97 use XML::Tags qw(
98 entry title author name link id published updated summary content
99 );
221c4151 100 my $web_url = $data->{web_url};
8509b33b 101 ' ', <entry>, "\n",
102 ' ', <title>, $data->{title}, </title>, "\n",
b0df368c 103 ' ', <author>, <name>, "Shadowcat Staff", </name>, </author>, "\n",
8509b33b 104 ' ', <link href="${web_url}" />, "\n",
da140bff 105 ' ', <id>, $web_url, </id>, "\n",
8509b33b 106 ' ', <published>, $data->{created}, </published>, "\n",
107 ' ', <updated>, ($data->{created}||$data->{updated}), </updated>, "\n",
221c4151 108 ($data->{summary_html}
b0df368c 109 ? (' ', <summary type="html">, \('<![CDATA['.$data->{summary_html}.']]>'), </summary>, "\n")
221c4151 110 : ()
111 ),
b0df368c 112 ' ', <content type="html">, \('<![CDATA['.$data->{content_html}.']]>'), </content>, "\n",
8509b33b 113 ' ', </entry>, "\n";
221c4151 114}
115
da140bff 116sub _absolutify_html {
117 my ($self, $html, $base_url, $page_url) = @_;
118 $html;
119}
120
221c4151 1211;