Better error message on bad _raw_page_plugins
[scpubgit/App-SCS.git] / lib / App / SCS / Page.pm
CommitLineData
632f0e07 1package App::SCS::Page;
2
3use IO::All;
4use Time::Local qw(timelocal);
632f0e07 5use List::Util qw(reduce);
0034f151 6use Module::Runtime qw(use_module);
18968192 7use HTML::Zoom;
632f0e07 8use Moo;
9
6b35e5c5 10has $_ => (is => 'ro', reader => "_$_", init_arg => $_) for qw(page_set);
f50b4a35 11
12sub _page_set_class { ref($_[0]->_page_set) }
13sub _top_dir { $_[0]->_page_set->top_dir }
14sub _my_path { io->dir($_[0]->_top_dir)->catdir($_[0]->path) }
15
632f0e07 16with 'App::SCS::Role::PageChildren';
17
18has $_ => (is => 'ro') for qw(
c68d9e18 19 title subtitle description keywords html created path
632f0e07 20);
21
c68d9e18 22has plugin_config => (is => 'rw', 'required' => 1);
632f0e07 23
24sub has_plugin_config { exists $_[0]->plugin_config->{$_[1]} }
25
26sub 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 }
c68d9e18 37 return $self->with(plugin_config => \@new);
632f0e07 38}
39
e2e7175f 40has _raw_page_plugins => (is => 'lazy', builder => sub {
632f0e07 41 my ($self) = @_;
42 my $plugin_config = $self->plugin_config;
0034f151 43 my ($plugin_map, $defaults) = @{$self->_page_set->plugin_config}
44 {qw(plugin_map defaults)};
632f0e07 45 my @spec = (@$defaults, @$plugin_config);
46 my @plugins;
47 while (my ($name, $config) = splice @spec, 0, 2) {
48 my $info = $plugin_map->{$name};
e244a007 49 die "No class for plugin name ${name}" unless $info->{class};
632f0e07 50 push @plugins,
51 use_module($info->{class})->new(
e2e7175f 52 ($info->{config}||sub{})->(), %$config, page => $self,
53 plugin_map => $plugin_map, # some things will need this
632f0e07 54 );
55 }
56 return \@plugins;
e2e7175f 57});
58
59has _page_plugins => (is => 'lazy', builder => sub {
60 my ($self) = @_;
61 my $raw = $self->_raw_page_plugins;
62 reduce { $b->filter_plugins($a) } $raw, @$raw;
63});
632f0e07 64
65sub published_at {
66 $_[0]->created
67 ? scalar localtime timelocal
68 map +(@{$_}[0..3], $_->[4]-1, $_->[5]-1900),
69 [ reverse split '\D+', $_[0]->created ]
70 : ''
71}
72
632f0e07 73sub to_app {
74 my ($self) = @_;
75 return sub { $self->to_psgi_response(@_) };
76}
77
78sub 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
88has _psgi_response => (is => 'lazy');
89
90sub _build__psgi_response {
91 my ($self) = @_;
92
632f0e07 93 my $psgi_res = [
0034f151 94 200, [ 'Content-type' => 'text/html' ], $self->_content_zoom->to_fh
632f0e07 95 ];
96
97 return reduce {
98 $b->filter_psgi_response($a)
0034f151 99 } $psgi_res, @{$self->_page_plugins};
100}
101
102sub _content_zoom {
103 my ($self) = @_;
104 return reduce {
105 $b->filter_content_zoom($a)
106 } $self->_html_zoom, @{$self->_page_plugins};
107}
108
109sub _html_zoom {
110 my ($self) = @_;
111 return reduce {
112 $b->filter_html_zoom($a)
113 } HTML::Zoom->from_html($self->html), @{$self->_page_plugins};
632f0e07 114}
115
18968192 116sub body {
117 my ($self) = @_;
118 HTML::Zoom->from_html($self->html)
119 ->collect(body => { into => \my @ev })
120 ->run;
121 HTML::Zoom->from_events(\@ev)->to_html;
122}
123
632f0e07 124no Moo;
125
126sub with {
127 my $self = shift;
128 return ref($self)->new(%$self, @_);
129}
130
1311;