sidebar filter
[scpubgit/SCS.git] / lib / SCSite.pm
CommitLineData
5cc6d9e2 1package SCSite;
2
3use IO::All;
4use SCSite::PageSet;
5use Web::Simple;
6
5cc6d9e2 7has pages => (is => 'lazy');
8
ebd4c292 9has filters => (is => 'lazy');
10
5cc6d9e2 11has _layout_zoom => (is => 'lazy');
12
13sub default_config {
14 (
15 pages_dir => 'share/content',
16 template_dir => 'share/skin',
17 )
18}
19
20sub _build_pages {
21 my ($self) = @_;
ebd4c292 22 SCSite::PageSet->new(base_dir => io->dir($self->config->{pages_dir}))
23}
24
25sub _build_filters {
26 my ($self) = @_;
27 require SCSite::SubListFilter;
fc436d2e 28 require SCSite::SidebarFilter;
29 +{
30 map +($_ => "SCSite::${_}Filter"->new_from_site($self)),
31 qw(SubList Sidebar)
32 }
5cc6d9e2 33}
34
35sub dispatch_request {
36 my $self = shift;
37 sub (/feed/**/) {
38 $self->_http_response(500 => 'text/plain' => 'Not implemented');
39 },
40 sub (/) {
41 $self->_page_http_response(200 => $self->_find_page('index'));
42 },
43 sub (/**) {
44 [ 302, [ 'Location' => "/$_[1]/" ], [] ]
45 },
46 sub (/**/) {
47 my ($code, $page) = map {
48 $_ ? (200, $_) : (404, $self->_error_page(404))
49 } $self->_find_page($_[1]);
50 $self->_page_http_response($code => $page);
51 }
52}
53
54sub _error_page {
55 my ($self, $code) = @_;
56 $self->_find_page("error_${code}");
57}
58
59sub _find_page {
60 my ($self, $path) = @_;
61 $self->pages->get({ path => $path });
62}
63
64sub _http_response {
65 my ($self, $code, $type, $content) = @_;
66 [ $code, [ 'Content-type' => $type ], [ $content ] ];
67}
68
69sub _page_http_response {
70 my ($self, $code, $page) = @_;
71 [ $code, [ 'Content-type' => 'text/html' ], $self->_render_page($page) ];
72}
73
74sub _render_page {
75 my ($self, $page) = @_;
76 my $zoom = $self->_layout_zoom;
fc436d2e 77 my %filters = %{$self->filters};
78 $zoom->select('.page.title')->replace_content($page->title)
5cc6d9e2 79 ->select('meta[name=description]')->replace_content($page->description)
80 ->select('meta[name=keywords]')->replace_content($page->keywords)
5cc6d9e2 81 ->select('.main')->replace_content(\$page->body)
fc436d2e 82 ->apply(sub {
83 foreach my $fname (sort keys %filters) {
84 my $cb = $filters{$fname}->callback_for($page);
85 $_ = $_->select(".${fname}")->collect({
86 filter => $cb, passthrough => 1
87 });
88 }
89 $_
ebd4c292 90 })
5cc6d9e2 91 ->to_fh
92}
93
94sub _build__layout_zoom {
95 my ($self) = @_;
96 HTML::Zoom->from_file(
97 io->dir($self->config->{template_dir})->catfile('layout.html')
98 )->memoize;
99}
100
101sub run_if_script {
102 return $_[0]->to_psgi_app if caller(1);
103 my $class = shift;
104 my @config_keys = keys %{{$class->default_config}};
105 require Getopt::Long;
106 my %config;
107 Getopt::Long::GetOptions(
108 map +("$_=s" => \$config{$_}), @config_keys
109 );
110 delete $config{$_} for grep !defined($config{$_}), keys %config;
111 my $new = $class->new(config => \%config);
112 $new->run(@_)
113}
114
115__PACKAGE__->run_if_script;