Per-directory config files
[scpubgit/App-SCS.git] / lib / App / SCS / Page.pm
CommitLineData
632f0e07 1package App::SCS::Page;
2
3use IO::All;
4use Time::Local qw(timelocal);
5use Data::Pond qw(pond_read_datum pond_write_datum);
6use List::Util qw(reduce);
0034f151 7use Module::Runtime qw(use_module);
18968192 8use HTML::Zoom;
632f0e07 9use Moo;
10
f50b4a35 11has "_$_" => (is => 'ro', init_arg => $_) for qw(page_set);
12
13sub _page_set_class { ref($_[0]->_page_set) }
14sub _top_dir { $_[0]->_page_set->top_dir }
15sub _my_path { io->dir($_[0]->_top_dir)->catdir($_[0]->path) }
16
632f0e07 17with 'App::SCS::Role::PageChildren';
18
19has $_ => (is => 'ro') for qw(
20 title subtitle description keywords plugins html created path
21);
22
23has plugin_config => (is => 'lazy');
24
25sub _build_plugin_config {
26 my ($self) = @_;
fea19fa9 27
28 my $pluginref = $self->plugins
632f0e07 29 ? pond_read_datum('[ '.$self->plugins.' ]')
fea19fa9 30 : [];
31
32 my @dirs = io->dir($self->path)->splitdir;
33 my $path = '';
34
35 foreach my $dir (@dirs) {
36 $path .= "/$dir";
37 #/home/.../share/pages/blog/config.pond etc
38
39 my $file = $self->_top_dir . "$path/config.pond";
40
41 next if !-f $file;
42
43 next if io($file)->empty;
44
45 my $content = io($file)->slurp;
46
47 my $config = pond_read_datum($content);
48 push @$pluginref, @{$config->{plugins}};
49 }
50
51
52 return $pluginref;
632f0e07 53}
54
55sub has_plugin_config { exists $_[0]->plugin_config->{$_[1]} }
56
57sub with_plugin_config {
58 my ($self, $with_name, $with_config) = @_;
59 my @orig = @{$self->plugin_config};
60 my @new;
61 while (my ($name, $config) = splice @orig, 0, 2) {
62 push @new, (
63 $name eq $with_name
64 ? ($name, { %$config, %$with_config })
65 : ($name, $config)
66 );
67 }
68 return $self->with(plugins => pond_write_datum(\@new));
69}
70
e2e7175f 71has _raw_page_plugins => (is => 'lazy', builder => sub {
632f0e07 72 my ($self) = @_;
73 my $plugin_config = $self->plugin_config;
0034f151 74 my ($plugin_map, $defaults) = @{$self->_page_set->plugin_config}
75 {qw(plugin_map defaults)};
632f0e07 76 my @spec = (@$defaults, @$plugin_config);
77 my @plugins;
78 while (my ($name, $config) = splice @spec, 0, 2) {
79 my $info = $plugin_map->{$name};
80 push @plugins,
81 use_module($info->{class})->new(
e2e7175f 82 ($info->{config}||sub{})->(), %$config, page => $self,
83 plugin_map => $plugin_map, # some things will need this
632f0e07 84 );
85 }
86 return \@plugins;
e2e7175f 87});
88
89has _page_plugins => (is => 'lazy', builder => sub {
90 my ($self) = @_;
91 my $raw = $self->_raw_page_plugins;
92 reduce { $b->filter_plugins($a) } $raw, @$raw;
93});
632f0e07 94
95sub published_at {
96 $_[0]->created
97 ? scalar localtime timelocal
98 map +(@{$_}[0..3], $_->[4]-1, $_->[5]-1900),
99 [ reverse split '\D+', $_[0]->created ]
100 : ''
101}
102
632f0e07 103sub to_app {
104 my ($self) = @_;
105 return sub { $self->to_psgi_response(@_) };
106}
107
108sub to_psgi_response {
109 my ($self, $env) = @_;
110
111 if (my $cb = $env->{'App::SCS::Command::Generate.extra_pages'}) {
112 $cb->($_->extra_pages) for @{$self->page_plugins};
113 }
114
115 $self->_psgi_response;
116}
117
118has _psgi_response => (is => 'lazy');
119
120sub _build__psgi_response {
121 my ($self) = @_;
122
632f0e07 123 my $psgi_res = [
0034f151 124 200, [ 'Content-type' => 'text/html' ], $self->_content_zoom->to_fh
632f0e07 125 ];
126
127 return reduce {
128 $b->filter_psgi_response($a)
0034f151 129 } $psgi_res, @{$self->_page_plugins};
130}
131
132sub _content_zoom {
133 my ($self) = @_;
134 return reduce {
135 $b->filter_content_zoom($a)
136 } $self->_html_zoom, @{$self->_page_plugins};
137}
138
139sub _html_zoom {
140 my ($self) = @_;
141 return reduce {
142 $b->filter_html_zoom($a)
143 } HTML::Zoom->from_html($self->html), @{$self->_page_plugins};
632f0e07 144}
145
18968192 146sub body {
147 my ($self) = @_;
148 HTML::Zoom->from_html($self->html)
149 ->collect(body => { into => \my @ev })
150 ->run;
151 HTML::Zoom->from_events(\@ev)->to_html;
152}
153
632f0e07 154no Moo;
155
156sub with {
157 my $self = shift;
158 return ref($self)->new(%$self, @_);
159}
160
1611;