1 package App::SCS::Page;
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 Module::Runtime qw(use_module);
11 has "_$_" => (is => 'ro', init_arg => $_) for qw(page_set);
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) }
17 with 'App::SCS::Role::PageChildren';
19 has $_ => (is => 'ro') for qw(
20 title subtitle description keywords plugins html created path
23 has plugin_config => (is => 'lazy');
25 sub _build_plugin_config {
28 my $pluginref = $self->plugins
29 ? pond_read_datum('[ '.$self->plugins.' ]')
32 my @dirs = io->dir($self->path)->splitdir;
36 foreach my $dir (@dirs) {
38 #/home/.../share/pages/blog/config.pond etc
40 my $file = $self->_top_dir . "$path/config.pond";
44 next if io($file)->empty;
46 my $content = io($file)->slurp;
48 my $config = pond_read_datum($content);
49 push @$pluginref, @{$config->{plugins}};
56 sub has_plugin_config { exists $_[0]->plugin_config->{$_[1]} }
58 sub with_plugin_config {
59 my ($self, $with_name, $with_config) = @_;
60 my @orig = @{$self->plugin_config};
62 while (my ($name, $config) = splice @orig, 0, 2) {
65 ? ($name, { %$config, %$with_config })
69 return $self->with(plugins => pond_write_datum(\@new));
72 has _raw_page_plugins => (is => 'lazy', builder => sub {
74 my $plugin_config = $self->plugin_config;
75 my ($plugin_map, $defaults) = @{$self->_page_set->plugin_config}
76 {qw(plugin_map defaults)};
77 my @spec = (@$defaults, @$plugin_config);
79 while (my ($name, $config) = splice @spec, 0, 2) {
80 my $info = $plugin_map->{$name};
82 use_module($info->{class})->new(
83 ($info->{config}||sub{})->(), %$config, page => $self,
84 plugin_map => $plugin_map, # some things will need this
90 has _page_plugins => (is => 'lazy', builder => sub {
92 my $raw = $self->_raw_page_plugins;
93 reduce { $b->filter_plugins($a) } $raw, @$raw;
98 ? scalar localtime timelocal
99 map +(@{$_}[0..3], $_->[4]-1, $_->[5]-1900),
100 [ reverse split '\D+', $_[0]->created ]
106 return sub { $self->to_psgi_response(@_) };
109 sub to_psgi_response {
110 my ($self, $env) = @_;
112 if (my $cb = $env->{'App::SCS::Command::Generate.extra_pages'}) {
113 $cb->($_->extra_pages) for @{$self->page_plugins};
116 $self->_psgi_response;
119 has _psgi_response => (is => 'lazy');
121 sub _build__psgi_response {
125 200, [ 'Content-type' => 'text/html' ], $self->_content_zoom->to_fh
129 $b->filter_psgi_response($a)
130 } $psgi_res, @{$self->_page_plugins};
136 $b->filter_content_zoom($a)
137 } $self->_html_zoom, @{$self->_page_plugins};
143 $b->filter_html_zoom($a)
144 } HTML::Zoom->from_html($self->html), @{$self->_page_plugins};
149 HTML::Zoom->from_html($self->html)
150 ->collect(body => { into => \my @ev })
152 HTML::Zoom->from_events(\@ev)->to_html;
159 return ref($self)->new(%$self, @_);