domain support for feeds, factor out sc-specific bits master
Matt S Trout [Tue, 7 Feb 2012 20:53:21 +0000 (20:53 +0000)]
lib/SCSite.pm
lib/SCSite/FeedGenerator.pm

index 69925c2..a5266cf 100755 (executable)
@@ -26,7 +26,7 @@ sub default_config {
     pages_dir => 'share/pages',
     template_dir => 'share/templates',
     static_dir => 'share/static',
-    feed_id_prefix => 'http://shadow.cat',
+    generate_host => 'www.example.com',
   )
 }
 
@@ -37,33 +37,17 @@ sub _build_pages {
 
 sub _build_filters {
   my ($self) = @_;
-  require SCSite::SubListFilter;
-  require SCSite::SidebarFilter;
   +{
-    map +($_ => "SCSite::${_}Filter"->new_from_site($self)),
-      qw(SubList Sidebar)
+    map {
+      require "SCSite/${_}Filter.pm";
+      +($_ => "SCSite::${_}Filter"->new_from_site($self))
+    } @{$self->config->{filters}}
   }
 }
 
 sub _build__feed_configs {
-  my $f = +{
-    'blog' => {
-      title => 'All Shadowcat blogs',
-      entries => { min_depth => 2, max_depth => 3 },
-    },
-    'blog/matt-s-trout' => {
-      title => q{Matt S Trout (mst)'s blog},
-      entries => { at_depth => 1 },
-    },
-    'blog/mark-keating' => {
-      title => q{Mark Keating (mdk)'s blog},
-      entries => { min_depth => 1, max_depth => 2 },
-    },
-    'news' => {
-      title => 'Shadowcat News',
-      entries => { at_depth => 4 },
-    },
-  };
+  my ($self) = @_;
+  my $f = $self->config->{feeds}||{};
   $f->{$_}{base} ||= $_ for keys %$f;
   $f;
 }
@@ -73,7 +57,6 @@ sub _build__feed_generator {
   require SCSite::FeedGenerator;
   SCSite::FeedGenerator->new(
     pages => $self->pages,
-    id_prefix => $self->config->{feed_id_prefix},
   );
 }
 
@@ -81,7 +64,7 @@ sub dispatch_request {
   my $self = shift;
   sub (/feed/**/) {
     if (my $conf = $self->_feed_configs->{$_[1]}) {
-      $self->_feed_http_response(200 => $conf);
+      $self->_feed_http_response(200 => $conf => $_[PSGI_ENV]);
     }
   },
   sub (/) {
@@ -157,16 +140,16 @@ sub _build__layout_zoom {
 
 sub run_if_script {
   return $_[0]->to_psgi_app if caller(1);
-  my $class = shift;
-  my @config_keys = keys %{{$class->default_config}};
+  my $self = ref($_[0]) ? $_[0] : $_[0]->new;
+  my @config_keys = keys %{{$self->default_config}};
   require Getopt::Long;
   my %config = map +($_ => $ENV{"SCS_${\uc $_}"}), @config_keys;
   Getopt::Long::GetOptions(
     map +("$_=s" => \$config{$_}), @config_keys
   );
   delete $config{$_} for grep !defined($config{$_}), keys %config;
-  my $new = $class->new(config => \%config);
-  $new->run(@_)
+  @{$self->config}{keys %config} = values %config;
+  $self->run(@_)
 }
 
 around _run_cli => sub {
@@ -196,22 +179,23 @@ sub _run_cli_generate {
     if (@spec) { '^('.join('|',map quotemeta($_),@spec).')' }
     else { '.' }
   };
+  my $prefix = 'http://'.$self->config->{generate_host};
   foreach my $path ('', $self->pages->all_paths) {
     next unless "$path/" =~ /$check/;
-    print "Generating ${path}\n";
+    print "Generating page ${path}\n";
     my $dir = $out->catdir($path);
     $dir->mkpath;
     $dir->catfile('index.html')->print(
-      $self->run_test_request(GET => "$path/")->content
+      $self->run_test_request(GET => "${prefix}${path}/")->content
     );
   }
   foreach my $path (map "/feed/$_/", keys %{$self->_feed_configs}) {
     next unless "$path/" =~ /$check/;
-    print "Generating ${path}\n";
+    print "Generating feed ${path}\n";
     my $dir = $out->catdir($path);
     $dir->mkpath;
     $dir->catfile('index.atom')->print(
-      $self->run_test_request(GET => $path)->content
+      $self->run_test_request(GET => "${prefix}${path}")->content
     );
   }
 }
index e8e28c1..104b8cc 100644 (file)
@@ -1,48 +1,62 @@
 package SCSite::FeedGenerator;
 
+use URI;
 use Moo;
 no warnings 'once';
 
-has id_prefix => (is => 'ro', required => 1);
 has pages => (is => 'ro', required => 1);
 
 sub feed_http_response {
-  my ($self, $code, $feed_config) = @_;
+  my ($self, $code, $feed_config, $env) = @_;
   $self->_feed_response(
-    $code, $self->_config_to_data($feed_config)
+    $code, $self->_config_to_data($feed_config, $env)
   );
 }
 
 sub _config_to_data {
-  my ($self, $config) = @_;
+  my ($self, $config, $env) = @_;
+  my $url_scheme = $env->{'psgi.url_scheme'} || "http";
+  my $url_port = $env->{SERVER_PORT}||80;
+  my $base_url = URI->new(
+    $url_scheme
+    .'://'
+    .($env->{HTTP_HOST}
+      or (
+        ($env->{SERVER_NAME} || "")
+        .($url_scheme eq 'http' && $url_port == 80
+           ? ''
+           : ":${url_port}"
+         )
+      ))
+    .($env->{SCRIPT_NAME} || '/')
+  );
+  my $abs = sub { URI->new_abs($_[0], $base_url)->as_string };
   my $base_page = $self->pages->get({ path => $config->{base} });
   my @entry_pages = $base_page->children(%{$config->{entries}})
                               ->latest(10)->flatten;
   my $updated = (sort map $_->created, @entry_pages)[-1];
   +{
      %$config,
-     id => $self->_id_for($base_page->path),
-     web_url => $base_page->path.'/',
-     feed_url => "/feed/${\$config->{base}}/",
+     id => $abs->("feed/${\$config->{base}}/"),
+     web_url => $abs->($config->{base}.'/'),
+     feed_url => $abs->("feed/${\$config->{base}}/"),
      updated => join('T', split(' ',$updated)).'Z',
-     entries => [ map +{
-       title => $_->title,
-       summary_html => do {
-         use HTML::Tags;
-         join '', HTML::Tags::to_html_string(<p>, $_->description, </p>)
-       },
-       content_html => $_->body,
-       created => join('T', split(' ',$_->created)).'Z',
-       web_url => $_->path,
-     }, @entry_pages ],
+     entries => [ map {
+      my $page_url = $abs->(do { (my $p = $_->path) =~ s/^\///; "$p/" });
+      +{
+         title => $_->title,
+         summary_html => do {
+           use HTML::Tags;
+           join '', HTML::Tags::to_html_string(<p>, $_->description, </p>)
+         },
+         content_html => $self->_absolutify_html($_->body, $base_url, $page_url),
+         created => join('T', split(' ',$_->created)).'Z',
+         web_url => $page_url,
+       }
+    } @entry_pages ],
   }
 }
 
-sub _id_for {
-  my ($self, $for) = @_;
-  join '', $self->id_prefix, $for;
-}
-
 sub _feed_response {
   my ($self, $code, $data) = @_;
   [ $code,
@@ -88,7 +102,7 @@ sub _entry_data_to_tags {
     '    ', <title>, $data->{title}, </title>, "\n",
     '    ', <author>, <name>, "Shadowcat Staff", </name>, </author>, "\n",
     '    ', <link href="${web_url}" />, "\n",
-    '    ', <id>, $self->_id_for($data->{web_url}), </id>, "\n",
+    '    ', <id>, $web_url, </id>, "\n",
     '    ', <published>, $data->{created}, </published>, "\n",
     '    ', <updated>, ($data->{created}||$data->{updated}), </updated>, "\n",
     ($data->{summary_html}
@@ -99,4 +113,9 @@ sub _entry_data_to_tags {
   '  ', </entry>, "\n";
 }
 
+sub _absolutify_html {
+  my ($self, $html, $base_url, $page_url) = @_;
+  $html;
+}
+
 1;