$page->body, custom plugin loading
[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) = @_;
27 $self->plugins
28 ? pond_read_datum('[ '.$self->plugins.' ]')
29 : []
30}
31
32sub has_plugin_config { exists $_[0]->plugin_config->{$_[1]} }
33
34sub with_plugin_config {
35 my ($self, $with_name, $with_config) = @_;
36 my @orig = @{$self->plugin_config};
37 my @new;
38 while (my ($name, $config) = splice @orig, 0, 2) {
39 push @new, (
40 $name eq $with_name
41 ? ($name, { %$config, %$with_config })
42 : ($name, $config)
43 );
44 }
45 return $self->with(plugins => pond_write_datum(\@new));
46}
47
48has _page_plugins => (is => 'lazy');
49
50sub _build__page_plugins {
51 my ($self) = @_;
52 my $plugin_config = $self->plugin_config;
0034f151 53 my ($plugin_map, $defaults) = @{$self->_page_set->plugin_config}
54 {qw(plugin_map defaults)};
632f0e07 55 my @spec = (@$defaults, @$plugin_config);
56 my @plugins;
57 while (my ($name, $config) = splice @spec, 0, 2) {
58 my $info = $plugin_map->{$name};
59 push @plugins,
60 use_module($info->{class})->new(
0034f151 61 ($info->{config}||sub{})->(), %$config, page => $self
632f0e07 62 );
63 }
64 return \@plugins;
65}
66
67sub published_at {
68 $_[0]->created
69 ? scalar localtime timelocal
70 map +(@{$_}[0..3], $_->[4]-1, $_->[5]-1900),
71 [ reverse split '\D+', $_[0]->created ]
72 : ''
73}
74
632f0e07 75sub to_app {
76 my ($self) = @_;
77 return sub { $self->to_psgi_response(@_) };
78}
79
80sub to_psgi_response {
81 my ($self, $env) = @_;
82
83 if (my $cb = $env->{'App::SCS::Command::Generate.extra_pages'}) {
84 $cb->($_->extra_pages) for @{$self->page_plugins};
85 }
86
87 $self->_psgi_response;
88}
89
90has _psgi_response => (is => 'lazy');
91
92sub _build__psgi_response {
93 my ($self) = @_;
94
632f0e07 95 my $psgi_res = [
0034f151 96 200, [ 'Content-type' => 'text/html' ], $self->_content_zoom->to_fh
632f0e07 97 ];
98
99 return reduce {
100 $b->filter_psgi_response($a)
0034f151 101 } $psgi_res, @{$self->_page_plugins};
102}
103
104sub _content_zoom {
105 my ($self) = @_;
106 return reduce {
107 $b->filter_content_zoom($a)
108 } $self->_html_zoom, @{$self->_page_plugins};
109}
110
111sub _html_zoom {
112 my ($self) = @_;
113 return reduce {
114 $b->filter_html_zoom($a)
115 } HTML::Zoom->from_html($self->html), @{$self->_page_plugins};
632f0e07 116}
117
18968192 118sub body {
119 my ($self) = @_;
120 HTML::Zoom->from_html($self->html)
121 ->collect(body => { into => \my @ev })
122 ->run;
123 HTML::Zoom->from_events(\@ev)->to_html;
124}
125
632f0e07 126no Moo;
127
128sub with {
129 my $self = shift;
130 return ref($self)->new(%$self, @_);
131}
132
1331;