use Test::Needs
[catagits/Web-Simple.git] / examples / bloggery / bloggery.cgi
CommitLineData
89166c1b 1#!/usr/bin/perl
2
5c33dda5 3use FindBin;
4use lib $FindBin::Bin.'/code';
5use Web::Simple 'Bloggery';
6
7package Bloggery::PostList;
8
9use File::stat;
10
11sub from_dir {
12 my ($class, $dir) = @_;
13 bless ({ dir => $dir }, $class);
14}
15
16sub all {
17 my ($self) = @_;
18 map { Bloggery::Post->from_file($_) }
19 sort { stat($a)->mtime <=> stat($b)->mtime }
20 grep { !/\.summary\.html$/ }
21 glob($self->{dir}.'/*.html');
22}
23
24sub post {
25 my ($self, $name) = @_;
26 my $file = $self->{dir}."/${name}.html";
27 return unless $file && -f $file;
28 return Bloggery::Post->from_file($file);
29}
30
d2a1d0c7 31sub map {
32 my ($self, $code) = @_;
33 map $code->($_), $self->all;
34}
35
5c33dda5 36package Bloggery::Post;
37
38sub from_file {
39 my ($class, $file) = @_;
40 bless({ file => $file }, $class);
41}
42
43sub name {
44 my $name = shift->{file};
45 $name =~ s/.*\///;
46 $name =~ s/\.html$//;
47 $name;
48}
49
50sub title {
51 my $title = shift->name;
52 $title =~ s/-/ /g;
53 $title;
54}
55
56sub html {
57 \do { local (@ARGV, $/) = shift->{file}; <> };
58}
59
60sub summary_html {
61 my $file = shift->{file};
62 $file =~ s/\.html$/.summary.html/;
63 return \'<p>No summary</p>' unless -f $file;
64 \do { local (@ARGV, $/) = $file; <> };
65}
66
67package Bloggery;
68
876e62e1 69has post_list => (is => 'lazy');
5c33dda5 70
876e62e1 71sub default_config {
72 (
73 title => 'Bloggery',
74 posts_dir => $FindBin::Bin.'/posts',
75 );
76}
77
78sub _build_post_list {
5c33dda5 79 my ($self) = @_;
876e62e1 80 Bloggery::PostList->from_dir(
81 $self->config->{posts_dir}
82 );
5c33dda5 83}
84
85sub post {
86 my ($self, $post) = @_;
87 $self->post_list->post($post);
88}
89
7274da22 90sub dispatch_request {
48cab33d 91 my $self = shift;
5c33dda5 92 sub (GET + /) {
876e62e1 93 redispatch_to '/index.html'
5c33dda5 94 },
4ed4fb42 95 sub (.html) {
876e62e1 96 response_filter { $self->render_html(@_) }
4ed4fb42 97 },
5c33dda5 98 sub (GET + /index) {
48cab33d 99 $self->post_list
5c33dda5 100 },
101 sub (GET + /*) {
48cab33d 102 $self->post($_[1])
5c33dda5 103 },
104 sub (GET) {
105 [ 404, [ 'Content-type', 'text/plain' ], [ 'Not found' ] ]
106 },
107 sub {
108 [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ]
109 },
92e23550 110};
5c33dda5 111
112sub render_html {
113 my ($self, $data) = @_;
114 use HTML::Tags;
115 return $data if ref($data) eq 'ARRAY';
116 return [
117 200,
118 [ 'Content-type', 'text/html' ],
119 [
120 HTML::Tags::to_html_string(
121 <html>,
122 <head>,
123 <title>, $self->title_for($data), </title>,
124 </head>,
125 <body>,
126 <h1>, $self->title_for($data), </h1>,
127 <div id="main">,
128 $self->main_html_for($data),
129 </div>,
130 </body>,
131 </html>
132 )
133 ]
134 ];
135}
136
137sub title_for {
138 my ($self, $data) = @_;
139 if ($data->isa('Bloggery::Post')) {
140 return $data->title;
141 }
142 return $self->config->{title};
143}
144
145sub main_html_for {
146 my ($self, $data) = @_;
147 use HTML::Tags;
148 if ($data->isa('Bloggery::Post')) {
149 $data->html
150 } elsif ($data->isa('Bloggery::PostList')) {
151 <ul>,
d2a1d0c7 152 $data->map(sub {
89166c1b 153 my $path = $_->name.'.html';
5c33dda5 154 <li>,
155 <h4>, <a href="$path">, $_->title, </a>, </h4>,
156 <span class="summary">, $_->summary_html, </span>,
157 </li>;
d2a1d0c7 158 }),
5c33dda5 159 </ul>;
160 } else {
161 <h2>, "Don't know how to render $data", </h2>;
162 }
163}
164
165Bloggery->run_if_script;