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); |
7 | use Moo; |
8 | |
9 | with 'App::SCS::Role::PageChildren'; |
10 | |
11 | has $_ => (is => 'ro') for qw( |
12 | title subtitle description keywords plugins html created path |
13 | ); |
14 | |
15 | has plugin_config => (is => 'lazy'); |
16 | |
17 | sub _build_plugin_config { |
18 | my ($self) = @_; |
19 | $self->plugins |
20 | ? pond_read_datum('[ '.$self->plugins.' ]') |
21 | : [] |
22 | } |
23 | |
24 | sub has_plugin_config { exists $_[0]->plugin_config->{$_[1]} } |
25 | |
26 | sub with_plugin_config { |
27 | my ($self, $with_name, $with_config) = @_; |
28 | my @orig = @{$self->plugin_config}; |
29 | my @new; |
30 | while (my ($name, $config) = splice @orig, 0, 2) { |
31 | push @new, ( |
32 | $name eq $with_name |
33 | ? ($name, { %$config, %$with_config }) |
34 | : ($name, $config) |
35 | ); |
36 | } |
37 | return $self->with(plugins => pond_write_datum(\@new)); |
38 | } |
39 | |
40 | has _page_plugins => (is => 'lazy'); |
41 | |
42 | sub _build__page_plugins { |
43 | my ($self) = @_; |
44 | my $plugin_config = $self->plugin_config; |
45 | my ($plugin_map, $defaults) = @{$self->_page_set}{qw(plugin_map defaults)}; |
46 | |
47 | my @spec = (@$defaults, @$plugin_config); |
48 | my @plugins; |
49 | while (my ($name, $config) = splice @spec, 0, 2) { |
50 | my $info = $plugin_map->{$name}; |
51 | push @plugins, |
52 | use_module($info->{class})->new( |
53 | %{$info->{config}||{}}, %$config, page => $self |
54 | ); |
55 | } |
56 | return \@plugins; |
57 | } |
58 | |
59 | sub published_at { |
60 | $_[0]->created |
61 | ? scalar localtime timelocal |
62 | map +(@{$_}[0..3], $_->[4]-1, $_->[5]-1900), |
63 | [ reverse split '\D+', $_[0]->created ] |
64 | : '' |
65 | } |
66 | |
67 | has "_$_" => (is => 'ro', init_arg => $_) for qw(page_set); |
68 | |
69 | sub _page_set_class { ref($_[0]->_page_set) } |
70 | sub _top_dir { $_[0]->_page_set->top_dir } |
71 | sub _my_path { io->dir($_[0]->_top_dir)->catdir($_[0]->path) } |
72 | |
73 | sub to_app { |
74 | my ($self) = @_; |
75 | return sub { $self->to_psgi_response(@_) }; |
76 | } |
77 | |
78 | sub to_psgi_response { |
79 | my ($self, $env) = @_; |
80 | |
81 | if (my $cb = $env->{'App::SCS::Command::Generate.extra_pages'}) { |
82 | $cb->($_->extra_pages) for @{$self->page_plugins}; |
83 | } |
84 | |
85 | $self->_psgi_response; |
86 | } |
87 | |
88 | has _psgi_response => (is => 'lazy'); |
89 | |
90 | sub _build__psgi_response { |
91 | my ($self) = @_; |
92 | |
93 | my @plugins = @{$self->page_plugins}; |
94 | |
95 | my $html_zoom = reduce { |
96 | $b->filter_html_zoom($a) |
97 | } HTML::Zoom->from_html($self->html), @plugins; |
98 | |
99 | my $content_zoom = reduce { |
100 | $b->filter_content_zoom($a) |
101 | } $html_zoom, @plugins; |
102 | |
103 | my $psgi_res = [ |
104 | 200, [ 'Content-type' => 'text/html' ], $content_zoom->to_fh |
105 | ]; |
106 | |
107 | return reduce { |
108 | $b->filter_psgi_response($a) |
109 | } $psgi_res, @plugins; |
110 | } |
111 | |
112 | no Moo; |
113 | |
114 | sub with { |
115 | my $self = shift; |
116 | return ref($self)->new(%$self, @_); |
117 | } |
118 | |
119 | 1; |