Commit | Line | Data |
632f0e07 |
1 | package App::SCS::Page; |
2 | |
3 | use IO::All; |
4 | use Time::Local qw(timelocal); |
5 | use Data::Pond qw(pond_read_datum pond_write_datum); |
6 | use List::Util qw(reduce); |
0034f151 |
7 | use Module::Runtime qw(use_module); |
18968192 |
8 | use HTML::Zoom; |
632f0e07 |
9 | use Moo; |
10 | |
f50b4a35 |
11 | has "_$_" => (is => 'ro', init_arg => $_) for qw(page_set); |
12 | |
13 | sub _page_set_class { ref($_[0]->_page_set) } |
14 | sub _top_dir { $_[0]->_page_set->top_dir } |
15 | sub _my_path { io->dir($_[0]->_top_dir)->catdir($_[0]->path) } |
16 | |
632f0e07 |
17 | with 'App::SCS::Role::PageChildren'; |
18 | |
19 | has $_ => (is => 'ro') for qw( |
20 | title subtitle description keywords plugins html created path |
21 | ); |
22 | |
23 | has plugin_config => (is => 'lazy'); |
24 | |
25 | sub _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 | |
55 | sub has_plugin_config { exists $_[0]->plugin_config->{$_[1]} } |
56 | |
57 | sub 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 |
71 | has _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 | |
89 | has _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 | |
95 | sub 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 |
103 | sub to_app { |
104 | my ($self) = @_; |
105 | return sub { $self->to_psgi_response(@_) }; |
106 | } |
107 | |
108 | sub 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 | |
118 | has _psgi_response => (is => 'lazy'); |
119 | |
120 | sub _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 | |
132 | sub _content_zoom { |
133 | my ($self) = @_; |
134 | return reduce { |
135 | $b->filter_content_zoom($a) |
136 | } $self->_html_zoom, @{$self->_page_plugins}; |
137 | } |
138 | |
139 | sub _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 |
146 | sub 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 |
154 | no Moo; |
155 | |
156 | sub with { |
157 | my $self = shift; |
158 | return ref($self)->new(%$self, @_); |
159 | } |
160 | |
161 | 1; |